mirror of
				https://github.com/stargieg/bacnet-stack
				synced 2025-10-26 23:35:52 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			282 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**************************************************************************
 | |
| *
 | |
| * Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
 | |
| * Multimedia Timer contribution by Cameron Crothers, 2008
 | |
| *
 | |
| * Permission is hereby granted, free of charge, to any person obtaining
 | |
| * a copy of this software and associated documentation files (the
 | |
| * "Software"), to deal in the Software without restriction, including
 | |
| * without limitation the rights to use, copy, modify, merge, publish,
 | |
| * distribute, sublicense, and/or sell copies of the Software, and to
 | |
| * permit persons to whom the Software is furnished to do so, subject to
 | |
| * the following conditions:
 | |
| *
 | |
| * The above copyright notice and this permission notice shall be included
 | |
| * in all copies or substantial portions of the Software.
 | |
| *
 | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 | |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 | |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| *
 | |
| *********************************************************************/
 | |
| #include <stdio.h>
 | |
| #include <stdbool.h>
 | |
| #include <stdint.h>
 | |
| #include <stdlib.h>
 | |
| #include <time.h>
 | |
| #define WIN32_LEAN_AND_MEAN
 | |
| #define STRICT 1
 | |
| #include <windows.h>
 | |
| #include "net.h"
 | |
| #include <MMSystem.h>
 | |
| #include "timer.h"
 | |
| 
 | |
| /* Offset between Windows epoch 1/1/1601 and
 | |
|    Unix epoch 1/1/1970 in 100 nanosec units */
 | |
| #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__BORLANDC__)
 | |
| #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
 | |
| #else
 | |
| #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
 | |
| #endif
 | |
| 
 | |
| /* counter for the various timers */
 | |
| static volatile uint32_t Millisecond_Counter[MAX_MILLISECOND_TIMERS];
 | |
| 
 | |
| /* Windows timer period - in milliseconds */
 | |
| static uint32_t Timer_Period = 1;
 | |
| 
 | |
| #if defined(_MSC_VER) || defined(__BORLANDC__)
 | |
| struct timezone {
 | |
|     int tz_minuteswest; /* minutes W of Greenwich */
 | |
|     int tz_dsttime;     /* type of dst correction */
 | |
| };
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: simulate the gettimeofday Linux function
 | |
| * Returns: zero
 | |
| * Note: The resolution of GetSystemTimeAsFileTime() is 15625 microseconds.
 | |
| * The resolution of _ftime() is about 16 milliseconds.
 | |
| * To get microseconds accuracy we need to use QueryPerformanceCounter or
 | |
| * timeGetTime for the elapsed time.
 | |
| *************************************************************************/
 | |
| 
 | |
| int gettimeofday(
 | |
|     struct timeval *tp,
 | |
|     void *tzp)
 | |
| {
 | |
|     static int tzflag = 0;
 | |
|     struct timezone *tz;
 | |
|     /* start calendar time in microseconds */
 | |
|     static LONGLONG usec_timer = 0;
 | |
|     LONGLONG usec_elapsed = 0;
 | |
|     /* elapsed time in milliseconds */
 | |
|     static uint32_t time_start = 0;
 | |
|     /* semi-accurate time from File Timer */
 | |
|     FILETIME ft;
 | |
|     uint32_t elapsed_milliseconds = 0;
 | |
| 
 | |
|     tzp = tzp;
 | |
|     if (usec_timer == 0) {
 | |
|         /* a 64-bit value representing the number of
 | |
|            100-nanosecond intervals since January 1, 1601 (UTC). */
 | |
|         GetSystemTimeAsFileTime(&ft);
 | |
|         usec_timer = ft.dwHighDateTime;
 | |
|         usec_timer <<= 32;
 | |
|         usec_timer |= ft.dwLowDateTime;
 | |
|         /*converting file time to unix epoch 1970 */
 | |
|         usec_timer /= 10;       /*convert into microseconds */
 | |
|         usec_timer -= DELTA_EPOCH_IN_MICROSECS;
 | |
|         tp->tv_sec = (long) (usec_timer / 1000000UL);
 | |
|         tp->tv_usec = (long) (usec_timer % 1000000UL);
 | |
|         time_start = timeGetTime();
 | |
|     } else {
 | |
|         elapsed_milliseconds = timeGetTime() - time_start;
 | |
|         usec_elapsed = usec_timer + ((LONGLONG) elapsed_milliseconds * 1000UL);
 | |
|         tp->tv_sec = (long) (usec_elapsed / 1000000UL);
 | |
|         tp->tv_usec = (long) (usec_elapsed % 1000000UL);
 | |
|     }
 | |
|     if (tzp) {
 | |
|         if (!tzflag) {
 | |
|             _tzset();
 | |
|             tzflag++;
 | |
|         }
 | |
|         tz = tzp;
 | |
|         tz->tz_minuteswest = _timezone / 60;
 | |
|         tz->tz_dsttime = _daylight;
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: returns the current millisecond count
 | |
| * Returns: none
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| uint32_t timer_milliseconds(
 | |
|     unsigned index)
 | |
| {
 | |
|     uint32_t now = timeGetTime();
 | |
|     uint32_t delta_time = 0;
 | |
| 
 | |
| 
 | |
|     if (index < MAX_MILLISECOND_TIMERS) {
 | |
|         if (Millisecond_Counter[index] <= now) {
 | |
|             delta_time = now - Millisecond_Counter[index];
 | |
|         } else {
 | |
|             delta_time = (UINT32_MAX - Millisecond_Counter[index]) + now + 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return delta_time;
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: compares the current time count with a value
 | |
| * Returns: true if the time has elapsed
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| bool timer_elapsed_milliseconds(
 | |
|     unsigned index,
 | |
|     uint32_t value)
 | |
| {
 | |
|     return (timer_milliseconds(index) >= value);
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: compares the current time count with a value
 | |
| * Returns: true if the time has elapsed
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| bool timer_elapsed_seconds(
 | |
|     unsigned index,
 | |
|     uint32_t seconds)
 | |
| {
 | |
|     return ((timer_milliseconds(index) / 1000) >= seconds);
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: compares the current time count with a value
 | |
| * Returns: true if the time has elapsed
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| bool timer_elapsed_minutes(
 | |
|     unsigned index,
 | |
|     uint32_t minutes)
 | |
| {
 | |
|     return ((timer_milliseconds(index) / (1000 * 60)) >= minutes);
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: Sets the timer counter to zero.
 | |
| * Returns: none
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| uint32_t timer_reset(
 | |
|     unsigned index)
 | |
| {
 | |
|     uint32_t timer_value = timer_milliseconds(index);
 | |
|     if (index < MAX_MILLISECOND_TIMERS) {
 | |
|         Millisecond_Counter[index] = timeGetTime();
 | |
|     }
 | |
|     return timer_value;
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: Shut down for timer
 | |
| * Returns: none
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| static void timer_cleanup(
 | |
|     void)
 | |
| {
 | |
|     timeEndPeriod(Timer_Period);
 | |
| }
 | |
| 
 | |
| /*************************************************************************
 | |
| * Description: Initialization for timer
 | |
| * Returns: none
 | |
| * Notes: none
 | |
| *************************************************************************/
 | |
| void timer_init(
 | |
|     void)
 | |
| {
 | |
|     TIMECAPS tc;
 | |
| 
 | |
|     /* set timer resolution */
 | |
|     if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
 | |
|         fprintf(stderr, "Failed to get timer resolution parameters\n");
 | |
|     }
 | |
|     /* configure for 1ms resolution - if possible */
 | |
|     Timer_Period = min(max(tc.wPeriodMin, 1L), tc.wPeriodMax);
 | |
|     if (Timer_Period != 1L) {
 | |
|         fprintf(stderr,
 | |
|             "Failed to set timer to 1ms.  " "Time period set to %ums\n",
 | |
|             (unsigned) Timer_Period);
 | |
|     }
 | |
|     timeBeginPeriod(Timer_Period);
 | |
|     atexit(timer_cleanup);
 | |
| }
 | |
| 
 | |
| #ifdef TEST_TIMER_WIN
 | |
| static uint32_t timeval_diff_ms(
 | |
|     struct timeval *old,
 | |
|     struct timeval *now)
 | |
| {
 | |
|     uint32_t ms = 0;
 | |
| 
 | |
|     /* convert to milliseconds */
 | |
|     ms = (now->tv_sec - old->tv_sec) * 1000 + (now->tv_usec -
 | |
|         old->tv_usec) / 1000;
 | |
| 
 | |
|     return ms;
 | |
| }
 | |
| 
 | |
| int main(
 | |
|     int argc,
 | |
|     char *argv[])
 | |
| {
 | |
|     long now = 0, last = 0, delta = 0;
 | |
|     struct timeval tv;
 | |
|     struct timeval old_tv = { 0 };
 | |
| 
 | |
|     timer_init();
 | |
|     printf("Testing granularity of timeGetTime()...\n");
 | |
|     timer_reset(0);
 | |
|     for (;;) {
 | |
|         now = timeGetTime();
 | |
|         delta = now - last;
 | |
|         if (delta) {
 | |
|             if (delta > 1) {
 | |
|                 printf("Delta is %ld.\n", delta);
 | |
|             }
 | |
|             last = now;
 | |
|         }
 | |
|         if (timer_elapsed_milliseconds(0, 5000)) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     printf("Testing granularity of gettimeofday()...\n");
 | |
|     for (;;) {
 | |
|         gettimeofday(&tv, NULL);
 | |
|         delta = timeval_diff_ms(&old_tv, &tv);
 | |
|         if (delta) {
 | |
|             if (delta > 1) {
 | |
|                 printf("Delta is %ld.\n", delta);
 | |
|             }
 | |
|             old_tv.tv_sec = tv.tv_sec;
 | |
|             old_tv.tv_usec = tv.tv_usec;
 | |
|         }
 | |
|         if (timer_elapsed_milliseconds(0, 10000)) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| #endif
 | 
