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

ticks to ms calculation

app_timer.h contains a useful macro for getting from milliseconds to a number of timer ticks, given a prescaler value with which the timer was started:

#define APP_TIMER_TICKS(MS, PRESCALER)\
        ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000))

Supposing I know a certain number of ticks have elapsed since a certain time, and I want to know how many milliseconds that is. Is there a macro for that? What would one look like? I have something here but it looks like it's overflowing long before it should.

  • well just re-arrange the formula, ignoring the ROUNDED_DIV() for simplicity

    APP_TIMER_TICKS = ( MS * APP_TIMER_CLOCK_FREQ ) / ( ( PRESCALAR + 1 ) * 1000 )
    

    so

    MS = APP_TIMER_TICKS * ( ( PRESCALAR + 1 ) * 1000 ) / APP_TIMER_CLOCK_FREQ
    

    I'm sure you can turn that into a define, not that it really helps you that much as the number of ticks will be in a variable so the compiler can't evaluate it and compile it out into a constant which is what happens most of the time with the current macro as usually everything on the right hand side is a compile-time constant.

  • The risk with just rearranging the formula in that macro is that you a) end up trying to use a uint64_t beyond the preprocessor and/or b) end up overflowing a uint32_t at a low number of ticks and getting a bogus result back. I settled on this function.

    uint32_t app_timer_ms(uint32_t ticks)
    {
    	// eg. (7 + 1) * 1000 / 32768
    	//   = 8000 / 32768
    	//   = 0.24414062
    	float numerator = ((float)APP_TIMER_PRESCALER + 1.0f) * 1000.0f;
    	float denominator = (float)APP_TIMER_CLOCK_FREQ;
    	float ms_per_tick = numerator / denominator;
    
    	uint32_t ms = ms_per_tick * ticks;
    
    	return ms;
    }
    
  • you imported the floating point emulation library just to do that? if you were using it anyway I guess that's ok. With a couple of ifs you can decide whether to do the multiplication or division first, or indeed use the uint64_t emulation which is quite fast and won't overflow. Either works.

  • I was already doing a lot with floats, so it's no big deal. I agree this is not ideal if you're not already using floats, good point.

Related