/////////////////////////////////////////////////////////////////////
// This open-source software sample is offered free of charge and without guarantee.
// Polhemus accepts no responsibility or liability for any use of this code.
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// Polhemus Inc., A Rockwell Collins Company www.polhemus.com
// © 2002-07 Polhemus Inc., All Rights Reserved
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//
//  Filename:           $Workfile: Debug.cpp $
//
//  Project Name:       Polhemus Tracker Command int32_terface API 
//
//  Original Author:    S. Gagnon
//
//  Description:        DOUT defs - replacement for OutputDebugString calls
//
//  VSS $Header: /Viper/VPlibusb.root/VPlibusb/VPlibusb/Debug.cpp 10    3/11/20 6:40p Suzanne $  
//
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
///@cond

//#ifdef _DEBUG
//#include "Windows.h"
//#include "stringapiset.h"
//#endif

#include "Debug.h"
#include <stdio.h>

//#include "EInvalParamHandler.h"
//#include "CriticalSection.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
#endif
using namespace iodbg;
/////////////////////////////////////////////////////////////////////
// CLASS PiDebug 
/////////////////////////////////////////////////////////////////////
char  PiDebug::m_szDebug[PI_DEBUG_BUFFER_SIZE] = "";
char  PiDebug::m_szDebugAlt[PI_DEBUG_BUFFER_SIZE] = "";
uint16_t PiDebug::m_usDebugLevel = 0;
bool PiDebug::m_bDebugCompact = false;
bool PiDebug::m_bLog = false;
bool PiDebug::m_bUseAlt = false;
//CLogFile PiDebug::m_LogFile;
//bool	PiDebug::g_bLogAscii = FALSE;
//bool	PiDebug::g_bFlushIO = TRUE;

PiDebug::PiDebug()
{
	//freopen("CONOUT$", "w", stdout);
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void
PiDebug::PIDOUT_ERR0( LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	PIDOUT_ERR( 0, szFormat, argptr );
}
void
PiDebug::PIDOUT_ERR1( LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	PIDOUT_ERR( 1, szFormat, argptr );
}
void
PiDebug::PIDOUT_ERR3( LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	PIDOUT_ERR( 3, szFormat, argptr );
}
void
PiDebug::PIDOUT_ERR5( LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	PIDOUT_ERR( 5, szFormat, argptr );
}
void
PiDebug::PIDOUT_ERR7( LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	PIDOUT_ERR( 7, szFormat, argptr );
}

void
PiDebug::PIDOUT_ERR( int32_t nLev, LPCSTR szFormat, ... )
{
	va_list argptr;
	va_start( argptr, szFormat );

	CHAR	szErrMsg[200];
	_strerror_s( szErrMsg, _countof(szErrMsg), szFormat );

//#ifdef _UNICODE
//	TCHAR * tstr = MBToWS( szErrMsg );
//	PIDebugOutL( nLev, tstr, argptr );
//	delete [] tstr;
//#else
	PIDebugOutL( nLev, szErrMsg, argptr );
//#endif
}

void
PiDebug::PIDOUT0( LPCSTR szFormat, ... )
{
    va_list argptr;
    va_start( argptr, szFormat );

    PIDebugOutL( 0, szFormat, argptr );
}
void
PiDebug::PIDOUT0_ALT(LPCSTR szFormat, ...)
{
	va_list argptr;
	va_start(argptr, szFormat);

	PIDebugOutL_ALT(0, szFormat, argptr);
}
/////////////////////////////////////////////////////////////////////
void
PiDebug::PIDOUT1( LPCSTR szFormat, ... )
{
    va_list argptr;
    va_start( argptr, szFormat );

    PIDebugOutL( 1, szFormat, argptr );
}
/////////////////////////////////////////////////////////////////////
void
PiDebug::PIDOUT3( LPCSTR szFormat, ... )
{
    va_list argptr;
    va_start( argptr, szFormat );

    PIDebugOutL( 3, szFormat, argptr );
}
void
PiDebug::PIDOUT3_ALT(LPCSTR szFormat, ...)
{
	va_list argptr;
	va_start(argptr, szFormat);

	PIDebugOutL_ALT(3, szFormat, argptr);
}
/////////////////////////////////////////////////////////////////////
void
PiDebug::PIDOUT5( LPCSTR szFormat, ... )
{
    va_list argptr;
    va_start( argptr, szFormat );

    PIDebugOutL( 5, szFormat, argptr );
}
void
PiDebug::PIDOUT5_ALT(LPCSTR szFormat, ...)
{
	va_list argptr;
	va_start(argptr, szFormat);

	PIDebugOutL_ALT(5, szFormat, argptr);
}
/////////////////////////////////////////////////////////////////////
void
PiDebug::PIDOUT7( LPCSTR szFormat, ... )
{
    va_list argptr;
    va_start( argptr, szFormat );

    PIDebugOutL( 7, szFormat, argptr );
}

void 
PiDebug::PIDebugOut( int32_t level, LPCSTR szFormat, ... ) 
{
    if (level < m_usDebugLevel)
    {
        int32_t iResult = 0;
        va_list argptr;
        va_start( argptr, szFormat );

        PIDOUTL( szFormat, argptr );
    }
}

void 
PiDebug::PIDebugOutL( int32_t level, LPCSTR szFormat, va_list argptr ) 
{
    if (level < m_usDebugLevel)
    {
        PIDOUTL( szFormat, argptr );
    }
}
void
PiDebug::PIDebugOutL_ALT(int32_t level, LPCSTR szFormat, va_list argptr)
{
	if (level < m_usDebugLevel)
	{
		PIDOUTL_ALT(szFormat, argptr);
	}
}
//void
//PiDebug::PIDOUTHEXBUF1( LPCTSTR szTitle, uint8_t * pBuf, uint32_t dwSize )
//{
//	if (g_usDebugLevel > 1)
//	{
//		PIDOUTHEXBUF( szTitle, pBuf, dwSize );
//	}
//}
//
//void
//PiDebug::PIDOUTHEXBUF( LPCTSTR szTitle, uint8_t * pBuf, uint32_t dwSize )
//{
//	CPiEInvalParamHandler iph(_T("PIDOUTHEXBUF"));
//	int32_t iOffset = 0;
//	//memset( (PVOID)g_szDebug, 0xAA, sizeof(g_szDebug) );
//	if (szTitle)
//	{
//		iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%s "), szTitle );
//	}
//
//	if (PiDebug::g_bLogAscii)
//	{
//		for (uint32_t i=0; (i<dwSize) && (iOffset<PI_DEBUG_BUFFER_SIZE-3); i++)
//		{
//			iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%c"), pBuf[i] );
//		}
//	}
//	else
//	{
//		for (uint32_t i=0; (i<dwSize) && (iOffset<PI_DEBUG_BUFFER_SIZE-3); i++)
//		{
//			iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%02x "), (BYTE)(pBuf[i]) );
//		}
//	}
//	//sprint32_tf( &(PiDebug::g_szDebug[iOffset]), "\n" );
//
//	g_szDebug[PI_DEBUG_BUFFER_SIZE-1] = 0;
//    ::OutputDebugString( PiDebug::g_szDebug );
//    ::OutputDebugString( _T("\n") );
//}
//
//void
//PiDebug::PILOGERR( LPCSTR szFormat, ... )
//{
//	CPiEInvalParamHandler iph(_T("PILOGERR"));
//
//	va_list argptr;
//	va_start( argptr, szFormat );
//
//	CHAR szErrMsg[200];
//	_strerror_s(szErrMsg, _countof(szErrMsg), szFormat );
//
//#ifdef _UNICODE
//	TCHAR * tstr = MBToWS( szErrMsg );
//	_stprint32_tf_s( PiDebug::g_szDebug, _countof( PiDebug::g_szDebug ), _T("%s "), tstr );
//	delete [] tstr;
//#else
//	_stprint32_tf_s( PiDebug::g_szDebug, _countof( PiDebug::g_szDebug ), _T("%s "), szErrMsg );
//#endif
//
//	LOGOUT( PiDebug::g_szDebug, argptr );
//}
//
//void
//PiDebug::PILOGHEXBUF( LPCTSTR szTitle, uint8_t * pBuf, uint32_t dwSize )
//{
//#ifdef _PIDEBUG_LOG
//	CPiEInvalParamHandler iph(_T("PILOGHEXBUF"));
//
//	int32_t iOffset = 0;
//	if (szTitle)
//	{
//		iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%s "), szTitle );
//	}
//
//	if (PiDebug::g_bLogAscii)
//	{
//		for (uint32_t i=0; (i<dwSize) && (iOffset<PI_DEBUG_BUFFER_SIZE-3); i++)
//		{
//			iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%c"), (BYTE)(pBuf[i]) );
//		}
//	}
//	else
//	{
//		for (uint32_t i=0; (i<dwSize) && (iOffset<PI_DEBUG_BUFFER_SIZE-3); i++)
//		{
//			iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%02x "), (BYTE)(pBuf[i]) );
//		}
//	}
//	//sprint32_tf( &(PiDebug::g_szDebug[iOffset]), "\n" );
//
//	g_szDebug[PI_DEBUG_BUFFER_SIZE-1] = 0;
//	g_LogFile.Write(_T("%s"), PiDebug::g_szDebug );
//	//FlushLog();
//#endif
//}
//
//void
//PiDebug::PIDOUTASCBUF( LPCTSTR szTitle, uint8_t * pBuf, uint32_t dwSize )
//{
//	CPiEInvalParamHandler iph(_T("PIDOUTASCBUF"));
//
//	int32_t iOffset = 0;
//	if (szTitle)
//	{
//		iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%s "), szTitle );
//	}
//
//	for (uint32_t i=0; (i<dwSize) && (iOffset<PI_DEBUG_BUFFER_SIZE-3); i++)
//	{
//		iOffset += _stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("%c"), pBuf[i] );
//	}
//
//	g_szDebug[PI_DEBUG_BUFFER_SIZE-1] = 0;
//	_stprint32_tf_s( &(PiDebug::g_szDebug[iOffset]), _countof(PiDebug::g_szDebug)-iOffset, _T("\n") );
//
//    ::OutputDebugString( PiDebug::g_szDebug );
//}
//

void 
PiDebug::PIDOUT( LPCSTR szFormat, ... )
{
// 	CPiEInvalParamHandler iph(_T("PIDOUT"));

    int32_t iResult = 0;
    va_list argptr;
    va_start( argptr, szFormat );

	int iFormattedLen = _vscprintf(szFormat, argptr);
	if (iFormattedLen + 1 <= PI_DEBUG_BUFFER_SIZE)
		iResult = vsprintf_s(PiDebug::m_szDebug, _countof(PiDebug::m_szDebug), szFormat, argptr);
	else
		sprintf_s(PiDebug::m_szDebug, sizeof(PiDebug::m_szDebug), "%s:%i : PiDebug::m_szDebug size %i too small for formatted len %i\r\n",
		__FUNCTION__, __LINE__, PI_DEBUG_BUFFER_SIZE, iFormattedLen);
//#endif
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

#ifdef _WINDOWS_
	::OutputDebugStringA(szThread);
	::OutputDebugStringA( PiDebug::m_szDebug );
#endif
	fprintf(stdout, "%s%s", szThread, PiDebug::m_szDebug);

}
//void myInvalidParameterHandler(const wchar_t* expression,
//   const wchar_t* function, 
//   const wchar_t* file, 
//   uint32_t line, 
//   uint64_t pReserved)
//{
//	TCHAR msg[500];
//	memset(msg, 0, sizeof(msg));
//
//
//#ifndef _UNICODE
//	TCHAR * texpression;
//	TCHAR * tfunction;
//	TCHAR * tfile;
//	texpression = PiDebug::WSToMB( expression );
//	tfunction = PiDebug::WSToMB( function );
//	tfile = PiDebug::WSToMB( file );
//	_sntprint32_tf_s( msg, 499, _TRUNCATE, _T("Invalid parameter detected in function %s.")
//									   _T(" File: %s Line: %d\n")
//									   _T("Expression: %s\n"), tfunction, tfile, line, texpression );
//	delete [] texpression;
//	delete [] tfunction;
//	delete [] tfile;
//#else
//	_sntprint32_tf_s( msg, 499, _TRUNCATE, _T("Invalid parameter detected in function %s.")
//									   _T(" File: %s Line: %d\n")
//									   _T("Expression: %s\n"), function, file, line, expression );
//#endif
//
//	MessageBox(NULL, msg, _T("PIDOUTL"), MB_OK );
//}
void
PiDebug::PIDOUTL_ALT(LPCSTR szFormat, va_list argptr)
{
	m_bUseAlt = true;

	PIDOUTLv(szFormat, argptr);

	m_bUseAlt = false;
}
void
PiDebug::PIDOUTLv(LPCSTR szFormat, va_list argptr)
{
	//	CPiEInvalParamHandler ph(_T("PIDOUTL"));
#ifdef _DEBUG
	CPiCriticalSection cs;
#endif
	char * pbuf = (m_bUseAlt) ? PiDebug::m_szDebugAlt : PiDebug::m_szDebug;
	size_t bufsize = (m_bUseAlt) ? _countof(PiDebug::m_szDebugAlt) : _countof(PiDebug::m_szDebug);

	int32_t iResult = 0;
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

	int iFormattedLen = _vscprintf(szFormat, argptr);
	//if (iFormattedLen + 1 <= PI_DEBUG_BUFFER_SIZE)
	if (iFormattedLen + strlen(szThread) + 1 <= PI_DEBUG_BUFFER_SIZE)
		iResult = vsprintf_s(pbuf, bufsize, szFormat, argptr);
	else
		sprintf_s(pbuf, bufsize, "%s:%i : PiDebug::%s size %i too small for formatted len %i\r\n",
			__FUNCTION__, __LINE__, (m_bUseAlt) ? "m_szDebugAlt" : "m_szDebug" , PI_DEBUG_BUFFER_SIZE, iFormattedLen);

#ifdef _WINDOWS_
	::OutputDebugStringA(szThread);
	::OutputDebugStringA(pbuf);
#endif
	fprintf(stdout, "%s%s", szThread, pbuf);

	//if (m_bLog)
	//	m_LogFile.VWrite(szFormat, argptr);

	pbuf[0] = 0;
}
void 
PiDebug::PIDOUTL( LPCSTR szFormat, va_list argptr )
{
//	CPiEInvalParamHandler ph(_T("PIDOUTL"));
#ifdef _DEBUG
 	CPiCriticalSection cs;
#endif
		
	int32_t iResult = 0;
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

	int iFormattedLen = _vscprintf(szFormat, argptr);
	//if (iFormattedLen + 1 <= PI_DEBUG_BUFFER_SIZE)
	if (iFormattedLen + strlen(szThread) + 1 <= PI_DEBUG_BUFFER_SIZE)
		iResult = vsprintf_s(PiDebug::m_szDebug, _countof(PiDebug::m_szDebug), szFormat, argptr);
	else
		sprintf_s(PiDebug::m_szDebug, _countof(PiDebug::m_szDebug), "%s:%i : PiDebug::m_szDebug size %i too small for formatted len %i\r\n",
		__FUNCTION__, __LINE__, PI_DEBUG_BUFFER_SIZE, iFormattedLen);

#ifdef _WINDOWS_
	::OutputDebugStringA( szThread );
    ::OutputDebugStringA( PiDebug::m_szDebug );
#endif
	fprintf(stdout, "%s%s", szThread, PiDebug::m_szDebug);

	//if (m_bLog)
	//	m_LogFile.VWrite(szFormat, argptr);

	PiDebug::m_szDebug[0] = 0;
}


LPWSTR 
PiDebug::MBToWS( LPCSTR szStr )
{
	WCHAR *	wstr = new WCHAR[ strlen(szStr)+1 ];

	mbtowc(wstr, szStr, strlen(szStr));

	wstr[strlen(szStr)]=0;

	return wstr;
}

LPSTR 
PiDebug::WSToMB( LPCWSTR szWStr )
{
	char * mbstr = 0; 
	size_t newsize = 0;
	errno_t r = wcstombs_s(&newsize, NULL, 0, szWStr, newsize);

	if (newsize)
	{
		mbstr = new char[newsize+1];
		size_t ns_II = 0;

		errno_t r = wcstombs_s(&ns_II, mbstr, newsize+1, szWStr, _TRUNCATE);
		mbstr[newsize] = 0;
	}
	return mbstr;
}

void
PiDebug::PIDOUTHEXBUF0(uint8_t * pBuf, int32_t iCount, bool bCR, const char *szPre)
{
	PIDOUTHEXBUF(pBuf, iCount, bCR, szPre, 0);
}
void
PiDebug::PIDOUTHEXBUF(uint8_t * pBuf, int32_t iCount, bool bCR, const char *szPre, uint16_t uLev/*= PID_3_NORMALIO*/)
{
	// only output hex buf if debuglevel is normal io or higher
	if (m_usDebugLevel < uLev)//PID_3_NORMALIO)//(m_usDebugLevel == 0)
		return;

	pidoutTraceFBuf(pBuf, iCount, bCR, szPre);

	return;
	/*
	if (((pBuf == 0) || (iCount == 0)) && (szPre != 0))
	{
		DOUT("%s : Empty buffer", (szPre != 0) ? szPre : "", m_szDebug, bCR ? "\r\n" : "");
		return;

	}
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

	int32_t iOffset = 0;
	iOffset += sprintf_s(&(m_szDebug[iOffset]), _countof(m_szDebug) - iOffset, "%s%s : %3d : ", szThread, (szPre != 0) ? szPre : "", iCount);

	for (int32_t i = 0; (i < iCount) && (iOffset < PI_DEBUG_BUFFER_SIZE - 10); i++)
	{
		iOffset += sprintf_s(&(m_szDebug[iOffset]), _countof(m_szDebug) - iOffset, "%02x ", pBuf[i]);
	}
	iOffset += sprintf_s(&(m_szDebug[iOffset]), _countof(m_szDebug) - iOffset, "%s", bCR ? "\r\n" : "");
	//DOUT("%s%s%s", (szPre != 0) ? szPre : "", m_szDebug, bCR ? "\r\n" : "");

#ifdef _WINDOWS_
	::OutputDebugStringA(PiDebug::m_szDebug);
#endif
	fprintf(stdout, "%s", PiDebug::m_szDebug);

	m_szDebug[0] = 0;
	*/
}
//////////////////////////////////////////
//////////////////////////////////////////
/**
*  Converts binary data to formated ASCII hex and ASCII characters. Each line contains eight hex values and
*  the 8 corresponding characters, if they are displayable. Characters such as line feed are printed as a '.'.
*  Example output:
*  ---------------
*  <tt>50 4C 55 43  18 00 00 00  PLUC....</tt><br>
*  <tt>01 00 00 00  0B 00 00 00  ........</tt><br>
*  <tt>01 00 00 00  00 00 00 00  ........</tt><br>
*  <tt>00 00 00 00  B7 26 00 00  .....&..</tt><br>
*
*  @note The bytes are printed as they are sent. This means that on a little endian machine the hex fields will
*        appear as if they are reversed.
*  @note ascii output ends with "\r\n"
*/
size_t pidoutConvert_data_to_ascii_hex(const void * data	/**< A pointer to the binary data to convert. */,
	size_t data_size	/**< Specifies the size in bytes of memory pointed to by data. */,
	char * out			/**< A pointer to a memory location where the ASCII hex and ASCII characters will be written. */,
	size_t out_size		/**< Specifies the size in bytes of memory pointed to by out. */,
	const char * pre	/**< ptr to char string to prepend to each line. May be zero. */)
{
	size_t i, j, k;
	uint32_t bytes[2];


	for (i = 0, j = 0; i < data_size && j + 15 < out_size - 1; ++i)
	{
		if ((pre) && (i % 8 == 0))
		{
			j += sprintf_s(&(out[j]), (out_size - j - 15), "%s", pre);
		}
		bytes[0] = ((unsigned char*)data)[i] / 16;
		bytes[1] = ((unsigned char*)data)[i] - 16 * bytes[0];

		for (k = 0; k < 2; ++k)
		{
			switch (bytes[k])
			{
			case 0:  out[j + k] = '0'; break;
			case 1:  out[j + k] = '1'; break;
			case 2:  out[j + k] = '2'; break;
			case 3:  out[j + k] = '3'; break;
			case 4:  out[j + k] = '4'; break;
			case 5:  out[j + k] = '5'; break;
			case 6:  out[j + k] = '6'; break;
			case 7:  out[j + k] = '7'; break;
			case 8:  out[j + k] = '8'; break;
			case 9:  out[j + k] = '9'; break;
			case 10: out[j + k] = 'A'; break;
			case 11: out[j + k] = 'B'; break;
			case 12: out[j + k] = 'C'; break;
			case 13: out[j + k] = 'D'; break;
			case 14: out[j + k] = 'E'; break;
			case 15: out[j + k] = 'F'; break;
			default: out[j + k] = '!';
			}
		}

		j += 2;

		if ((i + 1) % 8 == 0)
		{
			out[j] = ' '; ++j;
			out[j] = ' '; ++j;

			for (k = i - 7; k <= i; ++k, ++j)
			{
				out[j] = ((unsigned char*)data)[k];
				out[j] = (out[j] >= ' ' && out[j] <= '~') ? (out[j]) : ('.');
			}
		}
		else
			if ((i + 1) % 4 == 0)
			{
				out[j] = ' '; ++j;
				out[j] = ' '; ++j;

				if (i == data_size - 1)
				{
					for (k = 0; k < 13; ++k, ++j)
						out[j] = ' ';

					for (k = i - 3; k <= i; ++k, ++j)
					{
						out[j] = ((unsigned char*)data)[k];
						out[j] = (out[j] >= ' ' && out[j] <= '~') ? (out[j]) : ('.');
					}
				}
			}
			else
			{
				out[j] = ' '; ++j;
			}

		if ((i + 1) % 8 == 0 && i != data_size - 1)
		{
			out[j] = '\r'; ++j;
			out[j] = '\n'; ++j;
		}

		if (i == data_size - 1)
		{
			out[j] = '\r'; ++j;
			out[j] = '\n'; ++j;
			//out[j] = '\r'; ++j;
			//out[j] = '\n'; ++j;
		}
	}

	out[j] = '\0';

	return j;
}

void PiDebug::pidoutTraceFBuf(void * pBuf, int32_t iCount, bool bCR, const char *szPre)
{
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

	pidoutConvert_data_to_ascii_hex(pBuf, iCount, m_szDebug, PI_DEBUG_BUFFER_SIZE, 0);
	fprintf(stdout, "%s%s \r\n%s%s", szThread, (szPre != 0) ? szPre : "", m_szDebug, bCR ? "\r\n" : "");
#ifdef _WINDOWS_
	::OutputDebugStringA(PiDebug::m_szDebug);
#endif

	m_szDebug[0] = 0;
}

void
PiDebug::PIDOUTHEXBUF_ALT(uint8_t * pBuf, int32_t iCount, bool bCR, const char *szPre)
{
	// only output hex buf if debuglevel is normal io or higher
	if (m_usDebugLevel <= PID_3_NORMALIO)//(m_usDebugLevel == 0)
		return;

	if (((pBuf == 0) || (iCount == 0)) && (szPre != 0))
	{
		DOUT("%s : Empty buffer", (szPre != 0) ? szPre : "", m_szDebug, bCR ? "\r\n" : "");
		return;

	}
	char szThread[100];
	sprintf_s(szThread, 100, "[%08x] : ", (int)GetCurrentThreadId());

	int32_t iOffset = 0;
	iOffset += sprintf_s(&(PiDebug::m_szDebugAlt[iOffset]), _countof(PiDebug::m_szDebugAlt) - iOffset, "%s%s : %3d : ", szThread, (szPre != 0) ? szPre : "", iCount);

	for (int32_t i = 0; (i < iCount) && (iOffset < PI_DEBUG_BUFFER_SIZE - 5); i++)
	{
		iOffset += sprintf_s(&(PiDebug::m_szDebugAlt[iOffset]), _countof(PiDebug::m_szDebugAlt) - iOffset, "%02x ", pBuf[i]);
	}
	iOffset += sprintf_s(&(PiDebug::m_szDebugAlt[iOffset]), _countof(PiDebug::m_szDebugAlt) - iOffset, "%s", bCR ? "\r\n" : "");
	//DOUT("%s%s%s", (szPre != 0) ? szPre : "", m_szDebug, bCR ? "\r\n" : "");

#ifdef _WINDOWS_
	::OutputDebugStringA(PiDebug::m_szDebugAlt);
#endif
	fprintf(stdout, "%s", PiDebug::m_szDebugAlt);

	PiDebug::m_szDebugAlt[0] = 0;
}

/////////////////////////////////////////////////////////////////////
// END $Workfile: Debug.cpp $
/////////////////////////////////////////////////////////////////////
///@endcond
