#pragma once
//#include "VPif.h"
#include <string>
#include <stdint.h>
#include <memory.h>
#include <algorithm>
#include <complex>

//typedef struct _VP_PNO
//{
//	VP_FRAME_HDR hdr;
//	SEUPNO seupno;
//	SENFRAMEDATA sarr[SENSORS_PER_SEU];
//}VP_PNO;
//#define  VP_PNO_L VP_PNO

class CVPSeuPnoL : public CVPSeuPno
{
public:
	char *lRPT_szCRLF = RPT_CRLF;
	char *lRPT_szINDENT = "";
	void ReportHdr(std::string & s, bool bOneline = false, bool bZerobased = true, bool bAccel = false)
	{
		MakePrintable();

		uint32_t	nSeuID = seupno.seuid;// hubpno.hubid;
		uint32_t	nFrameNum = seupno.frame;
		uint32_t	nSCount = seupno.sensorCount;
		uint32_t	nPnoMode = seupno.HPinfo.bfPnoMode;
		int32_t     nAdd = (bZerobased) ? 0 : 1;

		//i += sizeof(SEUPNO_HDR);

		char szData[500];
		CVPSnsFrameA sd_a;

		if (bOneline)
		{
			//seuid + framename

			sprintf_s(szData, _countof(szData), "%2d  |  %07d  ", nSeuID + nAdd, nFrameNum);
			//sprintf_s(szData, _countof(szData), "%2d  |%c %07d  ", nSeuID + nAdd, chframerr, nFrameNum);
			s += szData;

			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA*  pSD = &(sarr[j]);
				float *pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//sensor num
				sprintf_s(szData, _countof(szData), "|  %2d  ",//  %c%c  %03d  %04x  |",
					pSD->SFinfo.bfSnum + nAdd);
				s += szData;

				//bitfields:stylus
				sprintf_s(szData, _countof(szData), "%c%c  ",
					b0, b1);
				s += szData;
				//bitfields:distortion
				sprintf_s(szData, _countof(szData), "%03d  ",
					dist);
				s += szData;
				//bitfields:aux
				sprintf_s(szData, _countof(szData), "%04x  ",
					aux);
				s += szData;

				//position
#ifndef _EP
				sprintf_s(szData, _countof(szData), "|  % 7.3f % 7.3f % 7.3f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#else
				sprintf_s(szData, _countof(szData), "|  % 7.5f % 7.5f % 7.5f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#endif
				s += szData;

				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.4f % 8.4f % 8.4f % 8.4f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.6f % 8.6f % 8.6f % 8.6f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#endif
				}
				else
				{
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.3f % 8.3f % 8.3f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.5f % 8.5f % 8.5f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#endif
				}
				s += szData;

				if (bAccel)
				{
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							" No_Accel \r\n");
					}
					else
					{
#ifndef _EP
						sprintf_s(szData, _countof(szData),
							" % 8.3f  % 8.3f  % 8.3f  % 8.3f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#else
						sprintf_s(szData, _countof(szData),
							" % 8.5f  % 8.5f  % 8.5f  % 8.5f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#endif
					}
					s += szData;
				}
			}
		}
		else //multi-line
		{
			lRPT_szCRLF = bAccel ? "" : RPT_CRLF;
			//for (uint32_t j = 0; j < nSCount; j++) 
			{
				SENFRAMEDATA*  pSD = &(sarr[0]);
				float *pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				const char * szPosu = CVPcmd::posunitsstr(pSD->SFinfo.bfPosUnits, false, true);
				const char * szOriu = CVPcmd::oriunitsstr(pSD->SFinfo.bfOriUnits, false, true);

				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//seu sens frame
				sprintf_s(szData, _countof(szData),
					//"%2d  %2d  %09d  ",
					//"12  12  123456789  ",
					"SEU Sns  FrameNum  ");
				s += szData;


				// bf: stylus
				sprintf_s(szData, _countof(szData),
					"BB  ");
				s += szData;

				//pos
#ifndef _EP
				sprintf_s(szData, _countof(szData),
					//"  %- 9.3f %- 9.3f %- 9.3f ");
					"  X(%s).... Y(%s).... Z(%s).... ", szPosu, szPosu, szPosu);
#else
				sprintf_s(szData, _countof(szData),
					//"  %- 9.5f %- 9.5f %- 9.5f ",
					"  X(%s).... Y(%s).... Z(%s).... ", szPosu, szPosu, szPosu);
#endif
				s += szData;
#ifndef _EP
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.4f %- 8.4f %- 8.4f %- 8.4f %s",
						" Qw...... Qx...... Qy...... Qz...... ");
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.3f %- 8.3f %- 8.3f %s",
						" Az(%3s). El(%3s). Ro(%3s). ", szOriu, szOriu, szOriu);
				}
#else
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.6f %- 8.6f %- 8.6f %- 8.6f %s",
						" Qw...... Qx...... Qy...... Qz...... ");
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.5f %- 8.5f %- 8.5f %s",
						" Az(%3s). El(%3s). Ro(%3s). ", szOriu, szOriu, szOriu);
				}

#endif
				s += szData;

				if (bAccel && pAccel)
				{
#ifndef _EP
					sprintf_s(szData, _countof(szData),
						//" % 8.3f  % 8.3f  % 8.3f  % 8.3f \r\n"
						//"Aa(X)5678AA12345678AA12345678AA12345678A");
						" a(X)....  a(Y)....  a(Z)....  a(R).... ");

#else
					sprintf_s(szData, _countof(szData),
						//" % 8.5f  % 8.5f  % 8.5f  % 8.5f \r\n"
						" a(X)....  a(Y)....  a(Z)....  a(R).... ");
#endif
					s += szData;
				}

			}
		}

	}
	void Report(std::string & s, bool bOneline = false, bool bZerobased = true, bool bAccel = false, bool bIFerrs = false)
	{
		MakePrintable();

		uint32_t	nSeuID = seupno.seuid;// hubpno.hubid;
		uint32_t	nFrameNum = seupno.frame;
		uint32_t	nSCount = seupno.sensorCount;
		uint32_t	nPnoMode = seupno.HPinfo.bfPnoMode;
		int32_t     nAdd = (bZerobased) ? 0 : 1;
		uint8_t     nframerr = bIFerrs ? seupno.HPinfo.bfReserved1 : 0;
		char		chframerr = nframerr ? '0' + nframerr : ' ';
		uint16_t     nframedrop = bIFerrs ? seupno.HPinfo.bfReserved2 : 0;
		if (nframedrop != 0)
		{
			int i = 0;
		}

		//i += sizeof(SEUPNO_HDR);

		char szData[500];
		CVPSnsFrameA sd_a;

		if (bOneline)
		{
			//seuid + framename

			//sprintf_s(szData, _countof(szData), "%3d |  %07d |  0x%04x ", nSeuID, nFrameNum, nDigIO);
			//sprintf_s(szData, _countof(szData), "%2d  |  %07d  ", nSeuID + nAdd, nFrameNum);
			if (nframedrop == 0)
				sprintf_s(szData, _countof(szData), "%2d  |%c %07d  ", nSeuID + nAdd, chframerr, nFrameNum);
			else
				sprintf_s(szData, _countof(szData), "%2d  |%c %07d(%1d)", nSeuID + nAdd, chframerr, nFrameNum, nframedrop);
			s += szData;

			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA*  pSD = &(sarr[j]);
				float *pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//sensor num + bitfields + position
				//sprintf_s(szData, _countof(szData), "|  %2d  %c%c  %03d  %04x  |  % 7.3f % 7.3f % 7.3f   |",
				//	pSD->SFinfo.bfSnum + nAdd, b0, b1, dist, aux, pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
				//s += szData;

				//sensor num + all bitfields
				//sprintf_s(szData, _countof(szData), "|  %2d  %c%c  %03d  %04x  |",
				//	pSD->SFinfo.bfSnum + nAdd, b0, b1, dist, aux);
				//s += szData;

				//sensor num
				sprintf_s(szData, _countof(szData), "|  %2d  ",//  %c%c  %03d  %04x  |",
					pSD->SFinfo.bfSnum + nAdd);
				s += szData;

				//all bitfields
				//sprintf_s(szData, _countof(szData), "  %c%c  %03d  %04x  |",
				//	b0, b1, dist, aux);
				//s += szData;

				//bitfields:stylus
				sprintf_s(szData, _countof(szData), "%c%c  ",
					b0, b1);
				s += szData;
				//bitfields:distortion
				sprintf_s(szData, _countof(szData), "%03d  ",
					dist);
				s += szData;
				//bitfields:aux
				sprintf_s(szData, _countof(szData), "%04x  ",
					aux);
				s += szData;

				//position
#ifndef _EP
				sprintf_s(szData, _countof(szData), "|  % 7.3f % 7.3f % 7.3f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#else
				sprintf_s(szData, _countof(szData), "|  % 7.5f % 7.5f % 7.5f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#endif
				s += szData;

				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					//sprintf_s(szData, _countof(szData), "| %3d  % 7.3f % 7.3f % 7.3f | % 8.4f % 8.4f % 8.4f % 8.4f ",
					//	pSD->SFinfo.bfSnum, pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2],
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.4f % 8.4f % 8.4f % 8.4f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.6f % 8.6f % 8.6f % 8.6f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#endif
				}
				else
				{
					//sprintf_s(szData, _countof(szData), "| %3d  % 7.3f % 7.3f % 7.3f | % 8.3f % 8.3f % 8.3f ",
					//	pSD->SFinfo.bfSnum, pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2],
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.3f % 8.3f % 8.3f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.5f % 8.5f % 8.5f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#endif
				}
				s += szData;

				if (bAccel)
				{
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							" No_Accel \r\n");
					}
					else
					{
#ifndef _EP
						sprintf_s(szData, _countof(szData),
							" % 8.3f  % 8.3f  % 8.3f  % 8.3f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#else
						sprintf_s(szData, _countof(szData),
							" % 8.5f  % 8.5f  % 8.5f  % 8.5f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#endif
					}
					s += szData;
				}
			}
		}
		else
		{
			lRPT_szCRLF = bAccel ? "" : RPT_CRLF;
			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA*  pSD = &(sarr[j]);
				float *pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;

				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//seu sens frame
				if (nframedrop == 0)
					sprintf_s(szData, _countof(szData),
					"%2d  %2d  %09d  ",
					nSeuID + nAdd, pSD->SFinfo.bfSnum + nAdd,
					nFrameNum);
				else
					sprintf_s(szData, _countof(szData),
						"%2d  %2d  %09d (%1d) ",
						nSeuID + nAdd, pSD->SFinfo.bfSnum + nAdd,
						nFrameNum, nframedrop);
				s += szData;

				// bf: stylus
				sprintf_s(szData, _countof(szData),
					"%c%c  ",
					b0, b1);
				s += szData;
				//// bf: dax
				//sprintf_s(szData, _countof(szData),
				//	"%03d  %04x  ",
				//	dist,aux);
				//s += szData;


				//pos
#ifndef _EP
				sprintf_s(szData, _countof(szData),
					//"  %- 9.3f %- 9.3f %- 9.3f ", //orig
					//"  %-09.3f %-09.3f %-09.3f ",
					"  %- 9.3f %- 9.3f %- 9.3f ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#else
				sprintf_s(szData, _countof(szData),
					"  %- 9.5f %- 9.5f %- 9.5f ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#endif
				s += szData;
#ifndef _EP
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.4f %- 8.4f %- 8.4f %- 8.4f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3],
						lRPT_szCRLF);
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.3f %- 8.3f %- 8.3f %s", //orig
						" %- 8.3f %- 8.3f %- 8.3f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2],
						lRPT_szCRLF);
				}
#else
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.6f %- 8.6f %- 8.6f %- 8.6f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3],
						lRPT_szCRLF);
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.5f %- 8.5f %- 8.5f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2],
						lRPT_szCRLF);
				}

#endif
				s += szData;

				if (bAccel)
				{
#ifndef _EP
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							"%s"
							, RPT_CRLF);
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							//" % 8.3f  % 8.3f  % 8.3f  % 8.3f %s"
							" %- 8.3f  %- 8.3f  %- 8.3f  %- 8.3f %s"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]
							, RPT_CRLF);
					}
#else
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							"%s"
							, RPT_CRLF);
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							" % 8.5f  % 8.5f  % 8.5f  % 8.5f %s"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]
							, RPT_CRLF);
					}
#endif
					s += szData;
				}

			}
		}

	}
	static void Report(VP_PNO* p, std::string& s, bool bOneline = false, bool bZerobased = true, bool bAccel = false, bool bIFerrs = false)
	{
		char* sRPT_szCRLF = RPT_CRLF;
		char* sRPT_szINDENT = "";
		//MakePrintable();

		uint32_t	nSeuID = p->seupno.seuid;// hubpno.hubid;
		uint32_t	nFrameNum = p->seupno.frame;
		uint32_t	nSCount = p->seupno.sensorCount;
		uint32_t	nPnoMode = p->seupno.HPinfo.bfPnoMode;
		int32_t     nAdd = (bZerobased) ? 0 : 1;
		uint8_t     nframerr = bIFerrs ? p->seupno.HPinfo.bfReserved1 : 0;
		char		chframerr = nframerr ? '0' + nframerr : ' ';
		uint16_t     nframedrop = bIFerrs ? p->seupno.HPinfo.bfReserved2 : 0;
		if (nframedrop != 0)
		{
			int i = 0;
		}
		//i += sizeof(SEUPNO_HDR);

		char szData[500];
		CVPSnsFrameA sd_a;

		if (bOneline)
		{
			//seuid + framename

			//sprintf_s(szData, _countof(szData), "%3d |  %07d |  0x%04x ", nSeuID, nFrameNum, nDigIO);
			//sprintf_s(szData, _countof(szData), "%2d  |  %07d  ", nSeuID + nAdd, nFrameNum);
			//sprintf_s(szData, _countof(szData), "%2d  |%c %07d  ", nSeuID + nAdd, chframerr, nFrameNum);
			if (nframedrop == 0)
				sprintf_s(szData, _countof(szData), "%2d  |%c %07d  ", nSeuID + nAdd, chframerr, nFrameNum);
			else
				sprintf_s(szData, _countof(szData), "%2d  |%c %07d(%1d)", nSeuID + nAdd, chframerr, nFrameNum, nframedrop);
			s += szData;

			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA* pSD = &(p->sarr[j]);
				float* pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//sensor num
				sprintf_s(szData, _countof(szData), "|  %2d  ",//  %c%c  %03d  %04x  |",
					pSD->SFinfo.bfSnum + nAdd);
				s += szData;

				//bitfields:stylus
				sprintf_s(szData, _countof(szData), "%c%c  ",
					b0, b1);
				s += szData;
				//bitfields:distortion
				sprintf_s(szData, _countof(szData), "%03d  ",
					dist);
				s += szData;
				//bitfields:aux
				sprintf_s(szData, _countof(szData), "%04x  ",
					aux);
				s += szData;

				//position
#ifndef _EP
				sprintf_s(szData, _countof(szData), "|  % 7.3f % 7.3f % 7.3f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#else
				sprintf_s(szData, _countof(szData), "|  % 7.5f % 7.5f % 7.5f   ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#endif
				s += szData;

				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.4f % 8.4f % 8.4f % 8.4f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.6f % 8.6f % 8.6f % 8.6f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
#endif
				}
				else
				{
#ifndef _EP
					sprintf_s(szData, _countof(szData), "|  % 8.3f % 8.3f % 8.3f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#else
					sprintf_s(szData, _countof(szData), "|  % 8.5f % 8.5f % 8.5f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
#endif
				}
				s += szData;

				if (bAccel)
				{
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							" No_Accel \r\n");
					}
					else
					{
#ifndef _EP
						sprintf_s(szData, _countof(szData),
							" % 8.3f  % 8.3f  % 8.3f  % 8.3f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#else
						sprintf_s(szData, _countof(szData),
							" % 8.5f  % 8.5f  % 8.5f  % 8.5f \r\n"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
#endif
					}
					s += szData;
				}
			}
		}
		else
		{
			sRPT_szCRLF = bAccel ? "" : RPT_CRLF;
			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA* pSD = &(p->sarr[j]);
				float* pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;

				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				//seu sens frame
				if (nframedrop == 0)
					sprintf_s(szData, _countof(szData),
						"%2d  %2d  %09d  ",
						nSeuID + nAdd, pSD->SFinfo.bfSnum + nAdd,
						nFrameNum);
				else
					sprintf_s(szData, _countof(szData),
						"%2d  %2d  %09d (%1d) ",
						nSeuID + nAdd, pSD->SFinfo.bfSnum + nAdd,
						nFrameNum, nframedrop);
				s += szData;

				// bf: stylus
				sprintf_s(szData, _countof(szData),
					"%c%c  ",
					b0, b1);
				s += szData;



				//pos
#ifndef _EP
				sprintf_s(szData, _countof(szData),
					//"  %- 9.3f %- 9.3f %- 9.3f ", //orig
					//"  %-09.3f %-09.3f %-09.3f ",
					"  %- 9.3f %- 9.3f %- 9.3f ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#else
				sprintf_s(szData, _countof(szData),
					"  %- 9.5f %- 9.5f %- 9.5f ",
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
#endif
				s += szData;
#ifndef _EP
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.4f %- 8.4f %- 8.4f %- 8.4f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3],
						sRPT_szCRLF);
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						//" %- 8.3f %- 8.3f %- 8.3f %s", //orig
						" %- 8.3f %- 8.3f %- 8.3f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2],
						sRPT_szCRLF);
				}
#else
				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.6f %- 8.6f %- 8.6f %- 8.6f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3],
						sRPT_szCRLF);
				}
				else
				{
					sprintf_s(szData, _countof(szData),
						" %- 8.5f %- 8.5f %- 8.5f %s",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2],
						sRPT_szCRLF);
				}

#endif
				s += szData;

				if (bAccel)
				{
#ifndef _EP
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							"%s"
							, RPT_CRLF);
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							//" % 8.3f  % 8.3f  % 8.3f  % 8.3f %s"
							" %- 8.3f  %- 8.3f  %- 8.3f  %- 8.3f %s"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]
							, RPT_CRLF);
					}
#else
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							"%s"
							, RPT_CRLF);
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							" % 8.5f  % 8.5f  % 8.5f  % 8.5f %s"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]
							, RPT_CRLF);
					}
#endif
					s += szData;
				}

			}
		}

	}
	void CSVHeader(std::string & s, bool bOneline = true, bool bAccel = true, bool bDispFrameErr = false)
	{
		MakePrintable();

		uint32_t	nSCount = seupno.sensorCount;
		uint32_t	nPnoMode = seupno.HPinfo.bfPnoMode;
		float *pAccel = 0;

		char szData[500];
		CVPSnsFrameA sd_a;
		if (bOneline)
		{
			if (bDispFrameErr)
				sprintf_s(szData, _countof(szData), "SEU, FrErr, Frame, raw drops");
			else
				sprintf_s(szData, _countof(szData), "SEU, Frame");
			s += szData;

			for (uint32_t j = 0; j < nSCount; j++)
			{
				s += ", ";
				SENFRAMEDATA*  pSD = &(sarr[j]);
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}
				sprintf_s(szData, _countof(szData), "Sensor, btn0, btn1, distortion, aux(hex), X, Y, Z, ");
				s += szData;


				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData), "Qw, Qx, Qy, Qz");
					s += szData;
				}
				else
				{	// extra comma added to end so it will use the same number of columns regardless of ori type
					sprintf_s(szData, _countof(szData), "Az, El, Rl,");
					s += szData;
				}
				if (bAccel && pAccel)
				{
					sprintf_s(szData, _countof(szData), ", a(X), a(Y), a(Z), a(R)");
					s += szData;
				}
				//s += szData;
			}
		}
		else
		{
			sprintf_s(szData, _countof(szData), "SEU, Frame, ");
			s += szData;
			sprintf_s(szData, _countof(szData), "Sensor, btn0, btn1, distortion, aux(hex), X, Y, Z, ");
			s += szData;

			SENFRAMEDATA *  pSD = &(sarr[0]);
			if (nPnoMode)
			{
				sd_a.Fill((SENFRAMEDATA_A*)pSD);
				pSD = sd_a;
				pAccel = sd_a.accel;
			}
			if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
			{
				sprintf_s(szData, _countof(szData), "Qw, Qx, Qy, Qz");
				s += szData;
			}
			else
			{	// extra comma added to end so it will use the same number of columns regardless of ori type
				sprintf_s(szData, _countof(szData), "Az, El, Rl");
				s += szData;
			}
			//s += szData;
			if (bAccel && pAccel)
			{
				sprintf_s(szData, _countof(szData), ",aX, aY, aZ, aRng");
				s += szData;
			}

		}

	}
	void CSVReport(std::string& s, bool bOneline = true, bool bAccel = true, bool bDispFrameErr = false)
	{
		MakePrintable();

		uint32_t	nSeuID = seupno.seuid;
		uint32_t	nFrameNum = seupno.frame;
		uint32_t	nSCount = seupno.sensorCount;
		uint32_t	nPnoMode = seupno.HPinfo.bfPnoMode;
		uint8_t     nframerr = bDispFrameErr ? HPreserved1() : 0;
		char		chframerr = nframerr ? ('0' + nframerr) : ' ';
		uint16_t	nframedrops = bDispFrameErr ? seupno.HPinfo.bfReserved2 : 0;
		if (nframedrops != 0)
		{
			int i = 0;
		}

		char szData[500];
		CVPSnsFrameA sd_a;
		if (bOneline)
		{
			if (bDispFrameErr)
				sprintf_s(szData, _countof(szData), "%3d, %d, %07d, %d", nSeuID, nframerr, nFrameNum, nframedrops);
			else
				sprintf_s(szData, _countof(szData), "%3d, %07d", nSeuID, nFrameNum);
			s += szData;

			for (uint32_t j = 0; j < nSCount; j++)
			{
				s += ", ";
				SENFRAMEDATA* pSD = &(sarr[j]);
				float* pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				sprintf_s(szData, _countof(szData), "%3d, %c, %c, %d, %x, % 7.3f, % 7.3f, % 7.3f, ",
					pSD->SFinfo.bfSnum, b0, b1, dist, aux,
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
				s += szData;

				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData), "  % 8.4f, % 8.4f, % 8.4f, % 8.4f",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
				}
				else
				{	// extra comma added to end so it will use the same number of columns regardless of ori type
					sprintf_s(szData, _countof(szData), " % 8.4f, % 8.4f, % 8.4f, ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
				}
				s += szData;
				if (bAccel)
				{
					if (!pAccel)
					{
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							", % 8.3f,% 8.3f,% 8.3f,% 8.3f"
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
						s += szData;
					}
				}
			}
		}
		else // multi-line
		{
			for (uint32_t j = 0; j < nSCount; j++)
			{
				SENFRAMEDATA* pSD = &(sarr[j]);
				float* pAccel = 0;
				char b0, b1;
				b0 = '0' + (pSD->SFinfo.bfBtnState0);
				b1 = '0' + (pSD->SFinfo.bfBtnState1);
				uint8_t dist = pSD->SFinfo.bfDistortion;
				uint16_t aux = pSD->SFinfo.bfAuxInput;
				if (nPnoMode)
				{
					sd_a.Fill((SENFRAMEDATA_A*)pSD);
					pSD = sd_a;
					pAccel = sd_a.accel;
				}

				sprintf_s(szData, _countof(szData), "%3d, %07d, %3d, %c, %c, %d, %x, % 7.3f, % 7.3f, % 7.3f, ",
					nSeuID, nFrameNum, pSD->SFinfo.bfSnum, b0, b1, dist, aux,
					pSD->pno.pos[0], pSD->pno.pos[1], pSD->pno.pos[2]);
				s += szData;

				if (pSD->SFinfo.bfOriUnits == ORI_QUATERNION)
				{
					sprintf_s(szData, _countof(szData), " % 8.4f, % 8.4f, % 8.4f, % 8.4f ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2], pSD->pno.ori[3]);
				}
				else
				{
					sprintf_s(szData, _countof(szData), " % 8.3f, % 8.3f, % 8.3f, ",
						pSD->pno.ori[0], pSD->pno.ori[1], pSD->pno.ori[2]);
				}
				s += szData;
				if (bAccel)
				{
					if (!pAccel)
					{
						sprintf_s(szData, _countof(szData),
							", No_Accel,");
					}
					else
					{
						sprintf_s(szData, _countof(szData),
							", % 8.3f,% 8.3f,% 8.3f,% 8.3f "
							, pAccel[0], pAccel[1], pAccel[2], pAccel[3]);
					}
					s += szData;
				}
				s += "\r\n";
			}
		}

	}
};
/*
CVPSeuPnoL()
{
Init();
}

CVPSeuPnoL(const CVPSeuPnoL & rv)
{
memcpy(&hdr, &rv.hdr, sizeof(VP_PNO_L));
}

CVPSeuPnoL(const VP_PNO_L * prv)
{
Init();
memcpy(&hdr, prv, sizeof(VP_PNO_L));
}

CVPSeuPnoL(uint8_t *p)
{
Init();
memcpy(&hdr, p, sizeof(VP_PNO_L));
}

operator VP_PNO_L * () { return (VP_PNO_L *)this; }

CVPSeuPnoL & operator= (const CVPSeuPnoL & rv)
{
memcpy(&hdr, &rv.hdr, sizeof(VP_PNO_L));
return *this;
}

CVPSeuPnoL & operator= (const VP_PNO_L * prv)
{
memcpy(&hdr, prv, sizeof(VP_PNO_L));
return *this;
}

CVPSeuPnoL & operator= (uint8_t *p)
{
memcpy(&hdr, p, sizeof(VP_PNO_L));
return *this;
}

uint32_t Extractraw(uint8_t *p)
{
if (!p)
return 0;

VP_FRAME_HDR *ph = (VP_FRAME_HDR*)p;
if (ph->preamble != VIPER_PNO_PREAMBLE)
return 0;

Init();
uint32_t index = 0;
memcpy(&hdr, ph, sizeof(VP_FRAME_HDR)); index += sizeof(VP_FRAME_HDR);
memcpy(&seupno, &p[index], sizeof(SEUPNO)); index += sizeof(SEUPNO);
for (uint32_t i = 0; i < seupno.sensorCount; i++)
{
memcpy(&sarr[i], &p[index], sizeof(SENFRAMEDATA)); index += sizeof(SENFRAMEDATA);
}

index += sizeof(VPCRC);
return index;
}
//p points to SEUPNO, no frame hdr, used for parsing Single Pno
uint32_t Extractseupno(uint8_t *p)
{
if (!p)
return 0;

//VP_FRAME_HDR *ph = (VP_FRAME_HDR*)p;
//if (ph->preamble != VIPER_PNO_PREAMBLE)
//	return 0;

Init();
uint32_t index = 0;
//memcpy(&hdr, ph, sizeof(VP_FRAME_HDR)); index += sizeof(VP_FRAME_HDR);
memcpy(&seupno, &p[index], sizeof(SEUPNO)); index += sizeof(SEUPNO);
for (uint32_t i = 0; i < seupno.sensorCount; i++)
{
memcpy(&sarr[i], &p[index], sizeof(SENFRAMEDATA)); index += sizeof(SENFRAMEDATA);
}

index += sizeof(VPCRC);
return index;
}

uint32_t SensorCount() const { return seupno.sensorCount; }

uint32_t SensorMap() const
{
uint32_t map = 0;

for (uint32_t i = 0; i < seupno.sensorCount; i++)
{
const SENFRAMEDATA*  pSD = &(sarr[i]);

map |= (1 << pSD->SFinfo.bfSnum);
}
return map;
}

SENFRAMEDATA * SensFrame(int i)
{
if (i < (int)SensorCount())
return &(sarr[i]);
else
return 0;
}

SENFRAMEDATA_A * SensFrameA(int i)
{
if (i < (int)SensorCount())
return (SENFRAMEDATA_A*)(&(sarr[i]));
else
return 0;
}

uint32_t Mode()
{
return seupno.HPinfo.bfPnoMode;
}

void SFUnits(int s, UNITS_CONFIG *pu)
{
SENFRAMEDATA * pSFD = Mode() ? (SENFRAMEDATA*)SensFrameA(s) : SensFrame(s);

if (pSFD && pu)
{
pu->pos_units = pSFD->SFinfo.bfPosUnits;
pu->ori_units = pSFD->SFinfo.bfOriUnits;
}
}

uint32_t BITerr()
{
return seupno.HPinfo.bfBITerr;
}

uint32_t	FrameNum()
{
return seupno.frame;
}

void Init()
{
memset(&hdr, 0, sizeof(VP_PNO_L));
}

void MakePrintable()
{

}


*/
