summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/attotime.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/attotime.h')
-rw-r--r--src/emu/attotime.h212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/emu/attotime.h b/src/emu/attotime.h
new file mode 100644
index 00000000000..8d7395b9d42
--- /dev/null
+++ b/src/emu/attotime.h
@@ -0,0 +1,212 @@
+/***************************************************************************
+
+ attotime.h
+
+ Support functions for working with attotime data.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Attotime is an attosecond-accurate timing system implemented as
+ 96-bit integers.
+
+ 1 second = 1e0 seconds
+ 1 millisecond = 1e-3 seconds
+ 1 microsecond = 1e-6 seconds
+ 1 nanosecond = 1e-9 seconds
+ 1 picosecond = 1e-12 seconds
+ 1 femtosecond = 1e-15 seconds
+ 1 attosecond = 1e-18 seconds
+
+ This may seem insanely accurate, but it has its uses when multiple
+ clocks in the system are run by independent crystals. It is also
+ useful to compute the attotime for something small, say 1 clock tick,
+ and still have it be accurate and useful for scaling.
+
+ Attotime consists of a 32-bit seconds count and a 64-bit attoseconds
+ count. Because the lower bits are kept as attoseconds and not as a
+ full 64-bit value, there is headroom to make some operations simpler.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ATTOTIME_H__
+#define __ATTOTIME_H__
+
+#include "mamecore.h"
+#include <math.h>
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define ATTOSECONDS_PER_SECOND_SQRT ((attoseconds_t)1000000000)
+#define ATTOSECONDS_PER_SECOND (ATTOSECONDS_PER_SECOND_SQRT * ATTOSECONDS_PER_SECOND_SQRT)
+#define ATTOSECONDS_PER_MILLISECOND (ATTOSECONDS_PER_SECOND / 1000)
+#define ATTOSECONDS_PER_MICROSECOND (ATTOSECONDS_PER_SECOND / 1000000)
+#define ATTOSECONDS_PER_NANOSECOND (ATTOSECONDS_PER_SECOND / 1000000000)
+
+#define ATTOTIME_MAX_SECONDS ((seconds_t)1000000000)
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* convert between a double and attoseconds */
+#define ATTOSECONDS_TO_DOUBLE(x) ((double)(x) * 1e-18)
+#define DOUBLE_TO_ATTOSECONDS(x) ((attoseconds_t)((x) * 1e18))
+
+/* convert between hertz (as a double) and attoseconds */
+#define ATTOSECONDS_TO_HZ(x) ((double)ATTOSECONDS_PER_SECOND / (double)(x))
+#define HZ_TO_ATTOSECONDS(x) ((attoseconds_t)(ATTOSECONDS_PER_SECOND / (x)))
+
+/* macros for converting other seconds types to attoseconds */
+#define ATTOSECONDS_IN_SEC(x) ((x) * ATTOSECONDS_PER_SECOND)
+#define ATTOSECONDS_IN_MSEC(x) ((x) * ATTOSECONDS_PER_MILLISECOND)
+#define ATTOSECONDS_IN_USEC(x) ((x) * ATTOSECONDS_PER_MICROSECOND)
+#define ATTOSECONDS_IN_NSEC(x) ((x) * ATTOSECONDS_PER_NANOSECOND)
+
+/* macros for building attotimes from other types at runtime */
+#define ATTOTIME_IN_HZ(hz) attotime_make(0, HZ_TO_ATTOSECONDS(hz))
+#define ATTOTIME_IN_SEC(s) attotime_make((s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */)
+#define ATTOTIME_IN_MSEC(ms) attotime_make((ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000))
+#define ATTOTIME_IN_USEC(us) attotime_make((us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000))
+#define ATTOTIME_IN_NSEC(ns) attotime_make((ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000))
+
+/* macros for building attotimes from other types at compile time */
+#define STATIC_ATTOTIME_IN_HZ(hz) { 0, HZ_TO_ATTOSECONDS(hz) }
+#define STATIC_ATTOTIME_IN_SEC(s) { (s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */ }
+#define STATIC_ATTOTIME_IN_MSEC(ms) { (ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000) }
+#define STATIC_ATTOTIME_IN_USEC(us) { (us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000) }
+#define STATIC_ATTOTIME_IN_NSEC(ns) { (ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000) }
+
+
+#define USEC_TO_ATTOSECONDS(us) ((attoseconds_t)((us) * ATTOSECONDS_PER_MICROSECOND))
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* core components of the attotime structure */
+typedef INT64 attoseconds_t;
+typedef INT32 seconds_t;
+
+
+/* the attotime structure itself */
+typedef struct _attotime attotime;
+struct _attotime
+{
+ seconds_t seconds;
+ attoseconds_t attoseconds;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* constant times for zero and never */
+extern const attotime attotime_zero;
+extern const attotime attotime_never;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* ----- conversion helpers ----- */
+
+/* convert an attotime to attoseconds, clamping to maximum positive/negative values */
+attoseconds_t attotime_to_attoseconds(attotime _time);
+
+
+/* ----- core math functions ----- */
+
+/* add two attotimes */
+attotime attotime_add(attotime _time1, attotime _time2);
+
+/* add attoseconds to an attotime */
+attotime attotime_add_attoseconds(attotime _time1, attoseconds_t _attoseconds);
+
+/* subtract two attotimes */
+attotime attotime_sub(attotime _time1, attotime _time2);
+
+/* subtract attoseconds from an attotime */
+attotime attotime_sub_attoseconds(attotime _time1, attoseconds_t _attoseconds);
+
+/* multiply an attotime by a constant */
+attotime attotime_mul(attotime _time1, UINT32 factor);
+
+/* divide an attotime by a constant */
+attotime attotime_div(attotime _time1, UINT32 factor);
+
+/* compare two attotimes */
+int attotime_compare(attotime _time1, attotime _time2);
+
+
+/* ----- misc utilities ----- */
+
+/* return a temporary printable string describing an attotime */
+const char *attotime_string(attotime _time, int precision);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ attotime_make - assemble an attotime from
+ seconds and attoseconds components
+-------------------------------------------------*/
+
+INLINE attotime attotime_make(seconds_t _secs, attoseconds_t _subsecs)
+{
+ attotime result;
+ result.seconds = _secs;
+ result.attoseconds = _subsecs;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_to_double - convert from attotime
+ to double
+-------------------------------------------------*/
+
+INLINE double attotime_to_double(attotime _time)
+{
+ return (double)_time.seconds + ATTOSECONDS_TO_DOUBLE(_time.attoseconds);
+}
+
+
+/*-------------------------------------------------
+ double_to_attotime - convert from double to
+ attotime
+-------------------------------------------------*/
+
+INLINE attotime double_to_attotime(double _time)
+{
+ attotime result;
+
+ /* set seconds to the integral part */
+ result.seconds = floor(_time);
+
+ /* set attoseconds to the fractional part */
+ _time -= (double)result.seconds;
+ result.attoseconds = DOUBLE_TO_ATTOSECONDS(_time);
+ return result;
+}
+
+
+#endif /* __ATTOTIME_H__ */