/* SPDX-License-Identifier: MIT */
/**
	@file		ntv2debugMacros.h
	@brief		Declares several macros useful for debugging.
	@copyright	(C) 2004-2022 AJA Video Systems, Inc.  All rights reserved.
**/

#ifndef DEBUGMACROS_H
#define DEBUGMACROS_H



// Macros common to all platforms

		// Decompose a UInt32 (or Mac "OSType") into 4 ASCII characters
		// Example:	 printf ("Type = %c%c%c%c\n", Make4CC(myType) );
//#define Make4CC(my4CC) ((char*)(&my4CC))[0], ((char*)(&my4CC))[1], ((char*)(&my4CC))[2], ((char*)(&my4CC))[3]

		// Advanced form: if the 'type' is a numeric value (i.e. 0 - 63), print as a decimal number.
		// Otherwise print as 4 characters.
#ifndef Make4CC
	#if TARGET_OS_WIN32 || TARGET_CPU_X86
		#define Make4CC(my4CC)	((my4CC < 0x40) ?  ' '						 : ((char*)(&my4CC))[3]), \
								((my4CC < 0x40) ?  ' '						 : ((char*)(&my4CC))[2]), \
								((my4CC < 0x40) ? ('0' + (char)(my4CC / 10)) : ((char*)(&my4CC))[1]), \
								((my4CC < 0x40) ? ('0' + (char)(my4CC % 10)) : ((char*)(&my4CC))[0])
	#else
		#define Make4CC(my4CC)	((my4CC < 0x40) ?  ' '						 : ((char*)(&my4CC))[0]), \
								((my4CC < 0x40) ?  ' '						 : ((char*)(&my4CC))[1]), \
								((my4CC < 0x40) ? ('0' + (char)(my4CC / 10)) : ((char*)(&my4CC))[2]), \
								((my4CC < 0x40) ? ('0' + (char)(my4CC % 10)) : ((char*)(&my4CC))[3])
	#endif
#endif


// Ping selectors
#define kPingOff				0

	// Muxer
#define kPingMuxerVBI			1
#define kPingAcThread			2
#define kPingDma				3
#define kPingMuxerAudioVox		4
#define kPingMuxerVideoVox		5

	// VideoOut
#define kPingFrameNotification	6
#define kPingCopyDrpToFrame		7
#define kPingEchoPortOut		8
#define kPingQTCallback			9

#define kPingAVSync				10

	// Transfer Codec
#define kPingXfrBandDecomp		11


	// VDig
#define kPingVDigFrameNotify	12
#define kPingVDigCompressOne	13
#define kPingVDigCompressDone	14

	// Use these for quickie tests
#define kPingTest1				15
#define kPingTest2				16
#define kPingTest3				17
#define kPingTest4				18



// Platform-specific macros

#ifdef AJAMac

	
		// For simple cases of measuring durations using the Mac "Microseconds" timer
		//
		// This assumes a pair of matching calls: "StartUSTimer(foo)" and "EndUSTimer(foo)", both within the
		// same scope (which rules out starting in one routine and ending in another - for that you have to
		// find global memory to hold the "start time"). Typical use is as follows:
		//
		//	TimerStart(foo)
		//		(code happens)
		//	TimerStop(foo)
		//
		//	and you'll get a printf that looks like:
		//		foo duration = xxx usecs
		//
		//	Note: no terminating ";"   Also, the variable passes to matching TimerStart() and TimerStop() calls must match.
		//	You may, however, use different variables in overlapping calls, such as:
		//
		//	TimerStart(foo)
		//		(code happens)
		//	TimerStart(bar)
		//		(more code happens)
		//	TimerStop(foo)
		//		(yet more...)
		//	TimerStop(bar)
		//
		//	You may use TimerLimit() instead of TimerStop() to specify a "limit" duration: the printf will only happen
		//	if the measured duration EXCEEDS the specified limit.
		
	#if (DEBUG) 
			// normal printf's
		#define TimerStart(a) UInt64 _startTime_##a, _endTime_##a;							\
								int _delta_##a;												\
								Microseconds((UnsignedWide*)&_startTime_##a);
								
		#define TimerStop(a) Microseconds((UnsignedWide*)&_endTime_##a);					\
							  _delta_##a = (int)U64Subtract(_endTime_##a, _startTime_##a);	\
							  printf (#a " duration = %d usecs\n", _delta_##a);

		#define TimerLimit(a,max) Microseconds((UnsignedWide*)&_endTime_##a);				\
							  _delta_##a = (int)U64Subtract(_endTime_##a, _startTime_##a);	\
							  if (_delta_##a >= max)										\
								printf (#a " duration = %d usecs\n", _delta_##a);

			// uses "dprintf" - which is assumed to be locally #define'd for LogProducer LogMsg
		#define LogTimerStart(a) UInt64 _startTime_##a, _endTime_##a;						\
								int _delta_##a;												\
								Microseconds((UnsignedWide*)&_startTime_##a);
								
		#define LogTimerStop(a) Microseconds((UnsignedWide*)&_endTime_##a);						\
								_delta_##a = (int)U64Subtract(_endTime_##a, _startTime_##a);	\
								dprintf (LOG_DEBUG, #a " duration = %d usecs\n", _delta_##a);
				
			// Mark time between successive function calls
		#define MarkTimeDelta(a)	static UInt64 _savedTime_##a = 0; UInt64 _currTime_##a; int _delta_##a; \
									Microseconds((UnsignedWide*)&_currTime_##a);							\
									_delta_##a = (int)U64Subtract(_currTime_##a, _savedTime_##a);			\
									printf (#a " duration = %d usecs\n", _delta_##a);						\
									_savedTime_##a = _currTime_##a;

	#else
			// disable for deployment builds
		#define TimerStart(a)
		#define TimerStop(a)
		#define TimerLimit(a,b)
		
		#define LogTimerStart(a)
		#define LogTimerStop(a)
		
		#define MarkTimeDelta(a)
	#endif


		// Sleazy (but quick) ways to tell if a Mac keyboard key is pressed
	#if (DEBUG) 
		#define shiftIsDown		( (GetCurrentKeyModifiers() & shiftKey)	  != 0 )
		#define capsLockIsDown	( (GetCurrentKeyModifiers() & alphaLock)  != 0 )
		#define optionIsDown	( (GetCurrentKeyModifiers() & optionKey)  != 0 )
		#define controlIsDown	( (GetCurrentKeyModifiers() & controlKey) != 0 )			
		#define commandIsDown	( (GetCurrentKeyModifiers() & cmdKey)	  != 0 )			
	#else	// !DEBUG
		#define shiftIsDown		false 
		#define capsLockIsDown	false
		#define optionIsDown	false
		#define controlIsDown	false
		#define commandIsDown	false
	#endif


#else	// !AJAMac


	#define TimerStart(a)
	#define TimerStop(a)

	#define shiftIsDown		false 
	#define capsLockIsDown	false
	#define optionIsDown	false
	#define controlIsDown	false
	#define commandIsDown	false

	#if DEBUG
		#define printf debugPrintf
		void debugPrintf (char *format, ...);
	#else
		#define printf dummyPrintf
		void dummyPrintf (char *format, ...);	// see SoftwareCodec.cpp
	#endif
	
#endif


#endif	// DEBUGMACROS_H
