make the timer have nanoseconds precision

Fri, 29 Mar 2024 00:03:25 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 29 Mar 2024 00:03:25 +0100
changeset 46
d3285aed65b3
parent 45
18de2af03531
child 47
44457f6cb0a2

make the timer have nanoseconds precision

src/ascension/context.h file | annotate | diff | comparison | revisions
src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/context.c file | annotate | diff | comparison | revisions
test/snake.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/ascension/context.h	Thu Mar 28 23:30:21 2024 +0100
     1.2 +++ b/src/ascension/context.h	Fri Mar 29 00:03:25 2024 +0100
     1.3 @@ -55,8 +55,8 @@
     1.4      unsigned int fonts_loaded;
     1.5      AscFont const *active_font;
     1.6      asc_col4i ink;
     1.7 -    unsigned int elapsed_millis;
     1.8 -    float elapsed;
     1.9 +    uint64_t frame_nanos;
    1.10 +    uint64_t total_nanos;
    1.11  } AscContext;
    1.12  
    1.13  /** Global ascension context. */
     2.1 --- a/src/ascension/datatypes.h	Thu Mar 28 23:30:21 2024 +0100
     2.2 +++ b/src/ascension/datatypes.h	Fri Mar 29 00:03:25 2024 +0100
     2.3 @@ -37,6 +37,14 @@
     2.4  #include <SDL2/SDL_pixels.h>
     2.5  
     2.6  // --------------------------------------------------------------------------
     2.7 +//    Useful Macros
     2.8 +// --------------------------------------------------------------------------
     2.9 +
    2.10 +#define ASC_NANOS_SECOND 1000000000ull
    2.11 +#define ASC_NANOS_MILLISECOND 1000000ull
    2.12 +#define ASC_NANOS_MICROSECOND 1000000ull
    2.13 +
    2.14 +// --------------------------------------------------------------------------
    2.15  //    Datatype Definitions
    2.16  // --------------------------------------------------------------------------
    2.17  
     3.1 --- a/src/context.c	Thu Mar 28 23:30:21 2024 +0100
     3.2 +++ b/src/context.c	Fri Mar 29 00:03:25 2024 +0100
     3.3 @@ -33,8 +33,16 @@
     3.4  #include <SDL2/SDL.h>
     3.5  #include <SDL2/SDL_ttf.h>
     3.6  
     3.7 +#include <time.h>
     3.8 +
     3.9  AscContext asc_context;
    3.10  
    3.11 +static uint64_t asc_nanos(void) {
    3.12 +    struct timespec ts;
    3.13 +    clock_gettime(CLOCK_MONOTONIC, &ts);
    3.14 +    return 1000000000ull*(uint64_t)ts.tv_sec + (uint64_t)ts.tv_nsec;
    3.15 +}
    3.16 +
    3.17  void asc_context_initialize(void) {
    3.18      if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED))
    3.19          return;
    3.20 @@ -58,6 +66,7 @@
    3.21          }
    3.22      }
    3.23      SDL_ClearError();
    3.24 +    asc_context.total_nanos = asc_nanos();
    3.25      asc_set_flag(&asc_context.flags, ASC_FLAG_INITILIZED);
    3.26      asc_dprintf("Ascension context initialized.");
    3.27  }
    3.28 @@ -128,11 +137,13 @@
    3.29      }
    3.30  
    3.31      // compute frame time
    3.32 -    static Uint32 ticks;
    3.33 -    Uint32 ticks_elapsed = SDL_GetTicks() - ticks;
    3.34 -    ticks = SDL_GetTicks();
    3.35 -    asc_context.elapsed_millis = ticks_elapsed;
    3.36 -    asc_context.elapsed = (float) ticks_elapsed / 1000.0f;
    3.37 +    uint64_t frame_nanos, ns;
    3.38 +    do {
    3.39 +        ns = asc_nanos();
    3.40 +        frame_nanos = ns - asc_context.total_nanos;
    3.41 +    } while (frame_nanos == 0);
    3.42 +    asc_context.frame_nanos = frame_nanos;
    3.43 +    asc_context.total_nanos = ns;
    3.44  
    3.45      return !asc_test_flag(asc_context.flags, ASC_FLAG_QUIT);
    3.46  }
     4.1 --- a/test/snake.c	Thu Mar 28 23:30:21 2024 +0100
     4.2 +++ b/test/snake.c	Fri Mar 29 00:03:25 2024 +0100
     4.3 @@ -29,18 +29,17 @@
     4.4  #include <cx/printf.h>
     4.5  
     4.6  static void update_fps_counter(AscSceneNode *node) {
     4.7 -    // addition and multiplication is more efficient testing for zero
     4.8 -    // at an unnoticeable cost of imprecision
     4.9 -    static unsigned last_fps = 0u;
    4.10 -    static unsigned debounce = 999u;
    4.11 -    unsigned fps = 1000u;
    4.12 -    debounce += asc_context.elapsed_millis;
    4.13 -    if (debounce >= 1000u) {
    4.14 +    static uint64_t last_fps = 0;
    4.15 +    static uint64_t debounce = ASC_NANOS_SECOND - 1;
    4.16 +    debounce += asc_context.frame_nanos;
    4.17 +    // only update text every seconds
    4.18 +    if (debounce >= ASC_NANOS_SECOND) {
    4.19          debounce = 0;
    4.20 -        fps /= asc_context.elapsed_millis;
    4.21 +        uint64_t fps = ASC_NANOS_SECOND;
    4.22 +        fps /= asc_context.frame_nanos;
    4.23          if (fps != last_fps) {
    4.24              last_fps = fps;
    4.25 -            snprintf(asc_text_data(node)->text, 9, "%u FPS", fps);
    4.26 +            snprintf(asc_text_data(node)->text, 11, "%"PRIu64" FPS", fps);
    4.27              asc_node_update(node);
    4.28          }
    4.29      }
    4.30 @@ -49,7 +48,7 @@
    4.31  static void create_fps_counter(void) {
    4.32      asc_set_font(asc_font(ASC_FONT_REGULAR, 24));
    4.33      asc_ink_rgb(255, 0, 0);
    4.34 -    AscSceneNode* node = asc_text(10, 10, "XXXXX FPS");
    4.35 +    AscSceneNode* node = asc_text(10, 10, "XXXXXXX FPS");
    4.36      asc_scene_add_behavior(node, update_fps_counter);
    4.37      asc_scene_add(&asc_window_active->ui, node);
    4.38  }

mercurial