enum
{
   // Command & Control Packet types
   PACKET_CC_STATUS_REQ    = 0x0C01, // cmd
   PACKET_CC_STATUS_TLM	   = 0x0C02, // tlm
   PACKET_CC_SCANNER_CFG   = 0x0C03, // cmd/tlm
   PACKET_CC_RTV_CFG	      = 0x0C04, // cmd/tlm
   PACKET_CC_CTD 	         = 0x0C05, // cmd
   PACKET_CC_TEXT          = 0x0C06, // tlm
   PACKET_CC_ACK  	      = 0x0C10, // tlm
   PACKET_CC_SCANNER_CFG2  = 0x0C11, // cmd/tlm
   PACKET_CC_STATUS_TLM2   = 0x0C12, // tlm
   PACKET_CC_LASER         = 0x0C13, // cmd - MBARI laser/attenuator
   PACKET_CC_ATTEN         = 0x0C14, // cmd - MBARI attenuator Control
   PACKET_CC_LSRTEC        = 0x0C15, // cmd - MBARI Laser TEC Control
   PACKET_CC_DETBIAS       = 0x0C16, // cmd - MBARI/Pipeline detector bias control
   PACKET_CC_PWR_MODE      = 0x0C17, // cmd - MBARI Power mode, 0=low, 1=normal
   PACKET_CC_OPERATE       = 0x0C0D, // cmd
   PACKET_CC_SYSTEM_CFG    = 0x0C0A, // cmd/tlm of user parameters
   PACKET_CC_SYSTEM_CFG2   = 0x0C0B, // cmd/tlm of factory parameters
   PACKET_CC_CGUI_REMOTE   = 0x0C3D, // cmd - remote commands
   PACKET_CC_CGUI_RMAP     = 0x0C3E, // tlm - remote map
   PACKET_CC_CGUI_LINK     = 0x0C3F, // tlm - remote NAV and Ship messages.

   PACKET_OPERATE_START    = 0x0001,
   PACKET_OPERATE_STOP     = 0x1000,
   PACKET_OPERATE_PT_ON    = 0x0010,
   PACKET_OPERATE_PT_OFF   = 0x0100,
   PACKET_OPERATE_PT_STOP  = 0x0110,
   PACKET_OPERATE_PT_ZERO  = 0x0120,
   PACKET_OPERATE_PT_HOME  = 0x0130,
   PACKET_OPERATE_PT_ICMDS = 0x0140,
   PACKET_OPERATE_RESTART  = 0x0150,
   PACKET_OPERATE_NOOP     = 0x0160, // change buffered Script config into a NO-Operation (skip)
   PACKET_OPERATE_CLEARSCRIPT = 0x0170, // clear script list
   PACKET_OPERATE_NEXTITEM = 0x0180, // stop/finish current scan and move to next script item
   PACKET_OPERATE_LASERP   = 0x0190, // immediate command to adjust laser power.
   PACKET_OPERATE_SHUTDOWN = 0xFFFF,

   //// Packet types that are REMOTE - in GlobalStruct. SAME workspace now (9/13/2022) DMF
   //REMOTE_CMD_NOOP = 0,
   //REMOTE_CMD_JOIN,         // add self to group
   //REMOTE_CMD_REMOVE,       // notification of leaving group or kick out of group.
   //REMOTE_CMD_REQUEST_CTRL, // asking to be the main controller - run the show - cmd Branches on way.
   //REMOTE_CMD_TIMEOUT_CTRL, // transition into a time mode that will allow another to take control.
   //REMOTE_CMD_GIVEUP_CTRL,  // transition into observer, giving up control
   //REMOTE_CMD_CLOSE_GROUP,  // reject all new requests to join, group closed
   //REMOTE_CMD_OPEN_GROUP,   // open the group up to new members
   //REMOTE_CMD_UPDATE,       // Update my data in the MAP - cmd Branches on way.
   //REMOTE_CMD_IO_RESET,     // Update my data in the MAP (IP address only?)
	// packet types - Normal EC commands
	PACKET_TYPE_UNKNOWN	      = 0x0D00,
	PACKET_TYPE_STATUS		   = 0x0D01, // older status
	//PACKET_TYPE_STATUSV02	   = 0x0D05,
	PACKET_TYPE_TEXT  		   = 0x0D02,
	PACKET_TYPE_DIGITIZER_CFG  = 0x0D03,
	PACKET_TYPE_SCANNER_CFG	   = 0x0D04,
   PACKET_TYPE_STATUSV02	   = 0x0D05, // newer status
	PACKET_TYPE_FULL_CFG		   = 0x0D06,
	PACKET_TYPE_EC_COMMAND	   = 0x0D10,
	PACKET_TYPE_MAN_ACQ		   = 0x0D11,
	PACKET_TYPE_TIME				= 0x0D15,
	PACKET_TYPE_TIME_HP			= 0x0D16,
	PACKET_TYPE_CAL				= 0x0D17,  // depricated
	PACKET_TYPE_ENV				= 0x0D18,
	PACKET_TYPE_SCANLOG			= 0x0D19,
	PACKET_TYPE_CTD				= 0x0D20,
   PACKET_TYPE_COMM				= 0x0D21,
   PACKET_TYPE_CFGS				= 0x0D22, // telemetry of Configuration User Specific
   PACKET_TYPE_STABILITY      = 0x0D23, // Az/El stability packet
   PACKET_TYPE_CFGS2				= 0x0D24, // telemetry of Configuration Factory specific

	PACKET_TYPE_EMERG_SHUTDOWN = 0x0D1A,	// two directional, used to inform GUI of error and for GUI to initiate power off

	EC_CMD_START_AUTO			   = 0x01,
	EC_CMD_STOP_AUTO,
	EC_CMD_START_MANUAL,
	EC_CMD_STOP_MANUAL,
	EC_CMD_START_MAN_ACQ,
	EC_CMD_STOP_MAN_ACQ,
	EC_CMD_START_LASER,
	EC_CMD_STOP_LASER,
	EC_CMD_AZ_POS_DEG,
	EC_CMD_EL_POS_DEG,
	EC_CMD_SCANNER_CAL,
	EC_CMD_SHUTDOWN,
	EC_CMD_DO_STDDEV,
	EC_CMD_MANUAL_IO,
	EC_CMD_PAN_TILT_POWER,
	EC_CMD_PAN_TILT_GOTO,
	EC_CMD_PAN_TILT_HOME,
	EC_CMD_PAN_TILT_ESTOP,
	EC_CMD_PITCH_ROLL_POWER,
	EC_CMD_AUX_SENSOR_POWER,
	EC_CMD_TAKE_VIBRATION, // was EC_CMD_SCANNER_CAL_AZ,
   EC_CMD_AZ_EL_POS_DEG,
   EC_CMD_MANUAL_USE_TZERO,
	EC_CMD_TEST_TRIGGER,
	EC_CMD_TEST_AZEL,

	EC_CMD_PAN_TILT_STOP,
	EC_CMD_PAN_TILT_ZERO,
   EC_CMD_PAN_TILT_ICMDS,
   EC_CMD_CONFIGS,    // command to ask for (could do both?) or compare user
   EC_CMD_RESTART_EC, // Restart EC and InstaCloud services
   EC_CMD_CONFIGS2,   // command to ask for (could do both?) or compare factory
   EC_CMD_NOOP,       // generic "do nothing"
   EC_CMD_LASER_GAIN, // immediate command to adjust laser power.
   EC_CMD_ATTEN_CTRL, // immediate attenuator control adjustment, MBARI (only)
   EC_CMD_LASER_TEC,  // Laser TEC control on/off and setpoint, MBARI (only)
   EC_CMD_DET_BIAS,   // Command to adjust detector bias settings (Pipeline/MBARI)

   EC_CMD_PWR_MODE,  // Shut down what we can - 0=lower power mode, 1=normal

	STRUCT_VERSION_02			= 0x02, // only 8 bits!
};

// ******************************************************************************** 
// ** Command and Control Interface (More Efficent cmd/tlm) data and headers
// ******************************************************************************** 
enum {
   HDR_VERSION_ICD				 = 0x0000, // Version 0 - just scans, original
   HDR_VERSION_ICD_V1	       = 0x0001, // Version 1 - added the pan tilt, Wait and Scripts
   HDR_VERSION_ICD_V2	       = 0x0002, // Version 2 - Modified headers to match CCI and Regular.
	HDR_CODE_ICD					 = 0x3DF0,

   FAULT_OCB_TEMP_C            = 1,      // OCBTemp_C    
   FAULT_OCB_HUMIDITY          = 1<<1,   // OCBHumidity  
   FAULT_PB_TEMP1_C            = 1<<2,   // PBTemp1_C    
   FAULT_PB_TEMP2_C            = 1<<3,   // PBTemp2_C    
   FAULT_PB_HUMIDITY           = 1<<4,   // PbHumidity   
   FAULT_DIG_TEMP_C            = 1<<5,   // DigTemp_C    
   FAULT_LASER_HS_TEMP_C       = 1<<6,   // LaserHsTemp_C
   FAULT_OPB_TEMP_C            = 1<<7,   // OpbTemp_C    
   FAULT_PT_SUPPLY_V           = 1<<8,   // PTSupply_V  
   FAULT_PT_CURRENT_A          = 1<<9,   // PTCurrent_A 
   FAULT_PT_LINEAR_COMP        = 1<<10,  // PTLinearComp 
   FAULT_PT_LEAK_V             = 1<<11,  // PTLeak_V     
   FAULT_PAN_TEMP_C            = 1<<12,  // PanTemp_C 
   FAULT_TILT_TEMP_C           = 1<<13,  // TiltTemp_C
   FAULT_WATCH_DOG_S           = 1<<14,  // Watchdog  
   FAULT_MIN_DEPTH_M           = 1<<15,  // MinDepth  
};

typedef struct
{
	UINT16     	nCfgNumber; 		      // unique configuration number identifier
	UINT8      	nGain; 			         // 1-12
	UINT8      	startProcessing_m;	   // # = m*255/50
	UINT8       endProcessing_m;		   // # = m*255/50
	UINT8			mode;	              	   // Scan type
	UINT16		numSamplesPerSegment;   // Digitizer samples per shot
	UINT16		nPtsPerScanLine;        // points per scan line
	UINT16		nPtsToAverage;          // Shots to average into one point
	UINT16		nScanLinesPerScan;      // Number of scan lines per scan file (even)
	INT16			azStart_degopt;		   // # = deg/30*32767
	INT16			azStop_degopt;		      // # = deg/30*32767
	INT16			elStart_degopt;		   // # = deg/30*32767
	INT16			elStop_degopt;		      // # = deg/30*32767
	//UINT8		PitchRollLogRate_s;	   // Time between logging pitch roll data, Always = 0 (no sensor)
   UINT8			Version;	               // This packet version number = 0
	UINT8       CTD_Source; 	         // See table for this
	UINT8			INU_Source; 		      // See table for this
	UINT8       Sync_Source; 		      // See table for this
	
   UINT8			bArchiveRaw 		:1;   // Archive RAW data (on sensor) – these get large!
	UINT8			bArchiveRiaat		:1;   // Archive RIAAT data (on sensor)
	UINT8			bEmergancyShutdown:1;	// 1 = If error system shuts down. Add explanation
	UINT8			nShareDrive		   :1;   // Always 0; 0 = D: 1 = C:  (allow debug)
	UINT8			nCfgDigitizer		:1;   // 0=(default) internal trigger; 1=external for OSS set =1
	UINT8			Spare             :3;

	UINT8			SENSOR_SERIAL_NUMBER; 	// 0xAB; A = SL#, B = sensor#; Always 0x20
	UINT16      nMinDepth_m;	         // Minimum Depth for scan, fault parameter
	UINT16		nStatusWatchdog_s;	   // Status request watchdog time in seconds, fault parameter
	UINT16      nFaultEnable;	         // Which faults are enabled/disabled see ICDStructFaultCode
	UINT16		Spare16;			         // Room to grow

} ICDStructScanConfig_v0;//v0

typedef struct
{
	UINT16     	nCfgNumber; 		      // unique configuration number identifier
	UINT8      	nGainEnd : 4; 			   // 1-12, sets laser power End
   UINT8      	nGain    : 4; 			   // 1-12, sets laser power Start   
	UINT8      	startProcessing_m;	   // # = m*255/50, start processing at this range
	UINT8       endProcessing_m;		   // # = m*255/50, end processing at this range
	UINT8			mode;	              	   // Scan type
	UINT16		numSamplesPerSegment;   // Digitizer samples per shot
	UINT16		nPtsPerScanLine;        // points per scan line
	UINT16		nPtsToAverage;          // Shots to average into one point
	UINT16		nScanLinesPerScan;      // Number of scan lines per scan file (even)
	INT16			azStart_degopt;		   // # = deg/30*32767, Az starting angle
	INT16			azStop_degopt;		      // # = deg/30*32767, Az ending angle
	INT16			elStart_degopt;		   // # = deg/30*32767, El starting angle
	INT16			elStop_degopt;		      // # = deg/30*32767, El ending angle
	UINT8			Version;	               // This packet version number = 1
	UINT8       CTD_Source; 	         // See table for this
	UINT8			INU_Source; 		      // See table for this
	UINT8       Sync_Source; 		      // See table for this
	
   UINT8			bArchiveRaw 		:1;   // Archive RAW data (on sensor) – these get large!
	UINT8			bArchiveRiaat		:1;   // Archive RIAAT data (on sensor)
	UINT8			bEmergancyShutdown:1;	// 1 = If error system shuts down. 0 = continue on error
	UINT8			nShareDrive		   :1;   // Usually 0; 0 = D: 1 = C:  (allow debug)
	UINT8			nCfgDigitizer		:1;   // 0=(default) internal trigger, SL3; 1=external trigger SL2
	UINT8			Spare             :3;

	UINT8			SENSOR_SERIAL_NUMBER; 	// 0xAB; A = SL#, B = sensor#; SL2 = 0x1#, SL2.5 = 0x2#, SL3 = 0x3#, SL4=0x4#, SL5=0x5#
	UINT16      nMinDepth_m;	         // Minimum Depth for scan, fault parameter
	UINT16		nStatusWatchdog_s;	   // Status request watchdog time in seconds, fault parameter
	UINT16      nFaultEnable;	         // Which faults are enabled/disabled see ICDStructFaultCode
	UINT16		Spare16;			         // Room to grow
   /////////////// v1 /////////////////// Added for PT control and file name //////////////
   UINT8      Subfolder[24];           // subfolder name
                                       // file is: <Time>_<Pan ang>_<Tilt ang>_<Gain>_<row>x<col>.riaat
   
   UINT32     nPan_deg     : 10;       // # = |deg|/360*511, Pan angle to go to
   UINT32     nTilt_deg    : 10;       // # = |deg|/360*511, Tilt angle to go to
   UINT32     bPanNeg      :  1;       // Pan  direction 1 = negitive, 0 = positive
   UINT32     bTiltNeg     :  1;       // Tilt direction 1 = negitive, 0 = positive
   UINT32     bPanTiltMove :  1;       // 1 = enable move, 0 = skip pan/tilt move, first action
   UINT32     bWaitEn      :  1;       // 1 = enable wait, 0 = skip wait, second action
   UINT32     bScanEn      :  1;       // 1 = enable scan, 0 = skip scan, third action
   UINT32     nWaitTimeS   :  7;       // 0-127 seconds length of time to wait

   UINT32     MountScanType:  2;       //{"ST","MO","ZZ"},  Scan Type Static, Motion, none
   UINT32     MountPanType :  2;       //{"PT","PA","3D", "ZZ"},  Pan Type Sidus Pan&Tilt, Sidus Pan, 3D, none
   UINT32     MountDir     :  3;       //{"PO","PD","DO","SD","ST","ZZ","IR"},  Direction Port, Port-down, down, starboard down, starboard, none
   UINT32     MountIns     :  2;       //{"PH","RO","ZZ"},  INS Type Phins, Rovins, none
   UINT32     MountCollar  :  1;       //{"CO","ZZ"}        Collar, none
   UINT32     MountCollar_mm: 10;      // mm of collar     
   UINT32     bNuclear     : 1;        // Nuclear sensor
   UINT32     SpareV1      : 11;       // room to grow. 

   UINT16     nNextCfgNumber;          // Continue onto next config (script-mode), 0=end.
} ICDStructScanConfig_v1; // version 1 which added pan tilt, wait, scripting size = 70 bytes


typedef struct
{
   UINT8			Version;	               // This packet version number = 5, - v2 moved
   UINT16     	nCfgNumber; 		      // unique configuration number identifier
   UINT8      	nGainEnd : 4; 			   // 1-12, sets laser power End
   UINT8      	nGain    : 4; 			   // 1-12, sets laser power Start   
   UINT8      	startProcessing_m;	   // # = m*255/50, start processing at this range
   UINT8       endProcessing_m;		   // # = m*255/50, end processing at this range
   UINT8			mode;	              	   // Scan type
   UINT16		numSamplesPerSegment;   // Digitizer samples per shot
   UINT16		nPtsPerScanLine;        // points per scan line
   UINT16		nPtsToAverage;          // Shots to average into one point
   UINT16		nScanLinesPerScan;      // Number of scan lines per scan file (even)
   INT16			azStart_degopt;		   // # = deg/30*32767, Az starting angle
   INT16			azStop_degopt;		      // # = deg/30*32767, Az ending angle
   INT16			elStart_degopt;		   // # = deg/30*32767, El starting angle
   INT16			elStop_degopt;		      // # = deg/30*32767, El ending angle
   //UINT8			Version;	            // This packet version number = 2, v2 moved this.
   UINT8       CTD_Source; 	         // See table for this
   UINT8			INU_Source; 		      // See table for this
   UINT8       Sync_Source; 		      // See table for this

   UINT8			bArchiveRaw        : 1;   // Archive RAW data (on sensor) – these get large!
   UINT8			bArchiveRiaat      : 1;   // Archive RIAAT data (on sensor)
   UINT8			bEmergancyShutdown : 1;	  // 1 = If error system shuts down. 0 = continue on error
   UINT8			nShareDrive        : 1;   // Usually 0; 0 = D: 1 = C:  (allow debug)
   UINT8			nCfgDigitizer      : 1;   // 0=(default) internal trigger, SL3; 1=external trigger SL2
   UINT8			Spare              : 3;
   // SENSOR_SERIAL_NUMBER is both: SENSOR_TYPE and SENSOR_SERIAL_NUMBER
   UINT8			SENSOR_TYPE;            // v2, 3=SL3, 4=SL4, 5=SL5
   UINT8			SENSOR_NUMBER; 	      // v2, SL<type>-# usually something like "005"
   UINT16      nMinDepth_m;	         // Minimum Depth for scan, fault parameter
   UINT16		nStatusWatchdog_s;	   // Status request watchdog time in seconds, fault parameter
   UINT16      nFaultEnable;	         // Which faults are enabled/disabled see ICDStructFaultCode

   /////////////// v1 /////////////////// Added for PT control and file name //////////////
   //UINT8      Subfolder[24];         // subfolder name - v2 moved

   UINT32     nPan_deg        : 13;      // v2, # = |deg|/360*8191, Pan  angle to go to (8191 was 511)
   UINT32     nTilt_deg       : 13;      // v2, # = |deg|/360*8191, Tilt angle to go to (8191 was 511)
   UINT32     bPanNeg         : 1;       // Pan  direction 1 = negitive, 0 = positive
   UINT32     bTiltNeg        : 1;       // Tilt direction 1 = negitive, 0 = positive
   UINT32     bPanTiltMove    : 1;       // 1 = enable move, 0 = skip pan/tilt move, first action
   UINT32     bWaitEn         : 1;       // 1 = enable wait, 0 = skip wait, second action
   UINT32     bScanEn         : 1;       // 1 = enable scan, 0 = skip scan, third action
   UINT32     bNoOp           : 1;       // v4, NoOp - disable this scan cfg when true. 

   UINT32     MountScanType   : 2;       //{"ST","MO","ZZ"},  Scan Type Static, Motion, none
   UINT32     MountPanType    : 3;       //v4 {"PT","PA","3D", "KY", "ZZ"},  Pan Type Sidus Pan&Tilt, Sidus Pan, 3D, none
   UINT32     MountDir        : 4;       //{"PO","PD","DO","SD","ST","ZZ","IR"},  Direction Port, Port-down, down, starboard down, starboard, none
   UINT32     MountIns        : 3;       //v5 {"PH","RO","SP","ZZ"},  INS Type Phins, Rovins, none
   UINT32     MountCollar     : 1;       //{"CO","ZZ"}        Collar, none
   UINT32     MountCollar_mm  : 10;      // mm of collar     
   UINT32     bNuclear        : 1;       // Nuclear sensor
   UINT32     Spare2          : 8;       //v5 moved nWaitTimeS : 9;// v2,v5 0-511 seconds length of time to wait
   
   UINT16     nNextCfgNumber;          // Continue onto next config (script-mode), 0=end.
   // size to here is 45 bytes + 24 (subfolder moved) = 69 (spare removed,SENSOR_TYPE added). 

   /////////////// v2 /////////////////// Updated to use with Remote Ops //////////////
   UINT8      JobName[24];            // job name
   UINT8      Subfolder[24];          // subfolder name, v2 moved
   UINT8      FileName[24];           // filename (if empty, will autogenerate one)
                                      // file auto is: <Time>_<Pan ang>_<Tilt ang>_<Gain>_<row>x<col>.riaat
   UINT8      nNumScans;              // repeat scan count, limit sets. (255==forever / continueous) to be implemented
   UINT16     nEstTimeS;              // Estimated time to run config in seconds  
   UINT8      nTotalScriptCnt;        // part of a sequence of this size. Updated for tlm only.
   UINT8      nLastRunStatus;         // 0=yet to run, 1=Running, 2=done good, 3=early exit, 3>=other errors. Updated for tlm only.
   UINT16     nWaitTimeS;
} ICDStructScanConfig; // version 5 which increased pan selectionn size for Kyst. Size = 122, now 124.


typedef struct
{
	UINT8		version;
	UINT16	nFaultCode;		         // Each bit is the status of a fault see ICDStructFaultCode
	UINT16	lastErrorNo;            // Error number that occurred

	UINT16	scanInOperation   :1;   // 0 = Standby,    1 = Scanning
	UINT16	nAutoModeStatus	:1;   // 0 = OFF,        1 = ON
	UINT16	nLaserStatus		:1;   // 0 = OFF,        1 = ON
	UINT16	nPitchRollStatus  :1;   // 0 = OFF,        1 = ON
	UINT16	bSystemInitialized:1;   // 0 = OFF,        1 = ON
	UINT16	nPPSGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nZdaGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nOCBGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nCTDGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nICloudGood       :1;   // 0 = Off/Failed, 1 = good
	UINT16	nRTVGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nNavGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	gain			      :4;   // 1-12 Laser Gain Current

	INT16		azScannerPos_deg;	      // deg = #*30/32767
	INT16		elScannerPos_deg;	      // deg = #*30/32767 for spinners it is Hz = #*50/32767
	UINT8		nScansCompletePcnt;	   // % = # ( 0 to 100)
	INT8		PBTemperature_C;		   // C = #/2 (+64 to -64)
	INT8		DiodeTemp_C;		      // C = #/2 (+64 to -64)
	INT8		CryTemp_C;		         // C = #/2 (+64 to -64)
	INT8		HeatSinkTemp_C;		   // C = #/2 (+64 to -64) Electronics
	INT8		LsrHeatSinkTemp_C;	   // C = #/2 (+64 to -64) Laser
	INT8		DigTemp_C;		         // C = #/2 (+64 to -64)
	INT8		DigCOSTemp_C;           // C = #/2 (+64 to -64) 
   INT8		OCBTemp_C;		         // C = #/2 (+64 to -64)
	INT8		OPBTemp_C;		         // C = #/2 (+64 to -64)
	UINT8		Voltage5;		         // V = #*6/256
	UINT8		Voltage3;		         // V = #*4/256
	UINT8		Humidity;		         // % = #*100/256
	UINT8    ScanPatternType;    	   // 0-5       
   INT16		pitch_deg;		         // deg = #*90/32767
	INT16		roll_deg;		         // deg = #*90/32767
	INT8		pitchRoll_temperature; 	// C = #/2 (+64 to -64)
	INT8		CTD_temperature_c;     	// C = #/2 (+64 to -64)
	UINT16	CTD_salinity_psu;	      // PSU = #*42/65535
	UINT16	CTD_pressure_dbar;   	// dBar = #/13 (5041.15 to 0)
	INT8		PBTemperature2_C;      	// C = #/2 (+64 to -64)
	UINT8		PBHumidity;           	// % = #*100/256
   
   ///////////////////////////////////////////////////////////
   // Unique status items for version 1 (order is after v0)
   UINT8    CommMode:     4;        // mode of the comm thread (pan, wait, scan)
   UINT8    EyeSafe:      1;        // Last eyesafe check passed
   UINT8    PanTiltModel: 2;        // None, Sidus pantilt, Sidus pan, 3D PanTilt
   UINT8    Spare:        1;
   
   UINT8    nPanTiltStatus;         // MSB Error        = bit 8 
                                    //     Move done    = bit 7
                                    //     Moving       = bit 6
                                    //     Homed        = bit 5
                                    //     Homing       = bit 4
                                    //     Initialized  = bit 3
                                    //     Initializing = bit 2
                                    // LSB Power On     = bit 1
   UINT8    ptMode;                 // See table
   UINT16   ptSwitches;             // MSB Stall state                  = bit 15 
                                    //     Error state                  = bit 14
                                    //     Received initialization cmds = bit 13
                                    //     Received Configuration       = bit 12
                                    //     Power enabled                = bit 11
                                    //     Initialized                  = bit 10
                                    //     Powered on                   = bit 9	 
                                    //     Accepted Stop command        = bit 8	 
                                    //     Request Stop                 = bit 7	 
                                    //     Tilt  stable                 = bit 6	 
                                    //     Pan stable                   = bit 5	 
                                    //     Reading position             = bit 4	 
                                    //     Homed                        = bit 3	 
                                    //     Initializing                 = bit 2	 
                                    //     Serial busy                  = bit 1	 
                                    // LSB Emergency Stop               = bit 0	 
   INT16	   PanPos_deg;	            // deg = #*360/32767
   UINT32   PanBrake    : 1;        // 1 = on, 0 = off
   UINT32   PanActive   : 1;        // 1 = active, 0=off
   UINT32   PanCurrent_A: 6;        // I  = #/63   (1 to 0)
   UINT32   PanSupply_V : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanComp_mm  : 6;        // mm = #      (63 to 0)
   UINT32   PanLeak_V   : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanTemp_C   : 6;        // C = # (63 to 0)

   INT16  	TiltPos_deg;	         // deg = #*360/32767
   UINT32   TiltBrake    : 1;       // 1 = on, 0 = off
   UINT32   TiltActive   : 1;       // 1 = active, 0=off
   UINT32   TiltCurrent_A: 6;       // I  = #/63   (1 to 0)
   UINT32   TiltSupply_V : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltComp_mm  : 6;       // mm = #      (63 to 0)
   UINT32   TiltLeak_V   : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltTemp_C   : 6;       // C = # (63 to 0)

   UINT16	nFaultEn;		         // Each bit is the status of a fault see ICDStructFaultCode
	// current CFG settings
	ICDStructScanConfig 	m_ScanCFG; // v5

} ICDStructStatus;


// Status data Small
typedef struct
{
	UINT8		version;
	UINT16	nFaultCode;		         // Each bit is the status of a fault see ICDStructFaultCode
	UINT16	lastErrorNo;            // Error number that occurred

	UINT16	scanInOperation   :1;   // 0 = Standby,    1 = Scanning
	UINT16	nAutoModeStatus	:1;   // 0 = OFF,        1 = ON
	UINT16	nLaserStatus		:1;   // 0 = OFF,        1 = ON
	UINT16	nPitchRollStatus  :1;   // 0 = OFF,        1 = ON
	UINT16	bSystemInitialized:1;   // 0 = OFF,        1 = ON
	UINT16	nPPSGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nZdaGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nOCBGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nCTDGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nICloudGood       :1;   // 0 = Off/Failed, 1 = good
	UINT16	nRTVGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nNavGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	gain			      :4;   // 1-12 Laser Gain Current

	INT16		azScannerPos_deg;	      // deg = #*30/32767
	INT16		elScannerPos_deg;	      // deg = #*30/32767
	UINT8		nScansCompletePcnt;	   // % = # ( 0 to 100)
	INT8		PBTemperature_C;		   // C = #/2 (+64 to -64)
	INT8		DiodeTemp_C;		      // C = #/2 (+64 to -64)
	INT8		CryTemp_C;		         // C = #/2 (+64 to -64)
	INT8		HeatSinkTemp_C;		   // C = #/2 (+64 to -64) Electronics
	INT8		LsrHeatSinkTemp_C;	   // C = #/2 (+64 to -64) Laser
	INT8		DigTemp_C;		         // C = #/2 (+64 to -64)
	INT8		DigCOSTemp_C;           // C = #/2 (+64 to -64) 
   INT8		OCBTemp_C;		         // C = #/2 (+64 to -64)
	INT8		OPBTemp_C;		         // C = #/2 (+64 to -64)
	UINT8		Voltage5;		         // V = #*6/256
	UINT8		Voltage3;		         // V = #*4/256
	UINT8		Humidity;		         // % = #*100/256
	UINT8    ScanPatternType;    	   // 0-5       
   INT16		pitch_deg;		         // deg = #*90/32767
	INT16		roll_deg;		         // deg = #*90/32767
	INT8		pitchRoll_temperature; 	// C = #/2 (+64 to -64)
	INT8		CTD_temperature_c;     	// C = #/2 (+64 to -64)
	UINT16	CTD_salinity_psu;	      // PSU = #*42/65535
	UINT16	CTD_pressure_dbar;   	// dBar = #/13 (5041.15 to 0)
	INT8		PBTemperature2_C;      	// C = #/2 (+64 to -64)
	UINT8		PBHumidity;           	// % = #*100/256
   
   ///////////////////////////////////////////////////////////
   // Unique status items for version 1 (order is after v0)
   UINT8    CommMode:     3;        // mode of the comm thread (pan, wait, scan)
   UINT8    EyeSafe:      1;        // Last eyesafe check passed
   UINT8    PanTiltModel: 2;        // None, Sidus pantilt, Sidus pan, 3D PanTilt
   UINT8    Spare:        2;
   
   UINT8    nPanTiltStatus;         // MSB Error        = bit 8 
                                    //     Move done    = bit 7
                                    //     Moving       = bit 6
                                    //     Homed        = bit 5
                                    //     Homing       = bit 4
                                    //     Initialized  = bit 3
                                    //     Initializing = bit 2
                                    // LSB Power On     = bit 1
   UINT8    ptMode;                 // See table
   UINT16   ptSwitches;             // MSB Stall state                  = bit 15 
                                    //     Error state                  = bit 14
                                    //     Received initialization cmds = bit 13
                                    //     Received Configuration       = bit 12
                                    //     Power enabled                = bit 11
                                    //     Initialized                  = bit 10
                                    //     Powered on                   = bit 9	 
                                    //     Accepted Stop command        = bit 8	 
                                    //     Request Stop                 = bit 7	 
                                    //     Tilt  stable                 = bit 6	 
                                    //     Pan stable                   = bit 5	 
                                    //     Reading position             = bit 4	 
                                    //     Homed                        = bit 3	 
                                    //     Initializing                 = bit 2	 
                                    //     Serial busy                  = bit 1	 
                                    // LSB Emergency Stop               = bit 0	 
   INT16	   PanPos_deg;	            // deg = #*360/32767
   UINT32   PanBrake    : 1;        // 1 = on, 0 = off
   UINT32   PanActive   : 1;        // 1 = active, 0=off
   UINT32   PanCurrent_A: 6;        // I  = #/63   (1 to 0)
   UINT32   PanSupply_V : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanComp_mm  : 6;        // mm = #      (63 to 0)
   UINT32   PanLeak_V   : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanTemp_C   : 6;        // C = # (63 to 0)

   INT16  	TiltPos_deg;	         // deg = #*360/32767
   UINT32   TiltBrake    : 1;       // 1 = on, 0 = off
   UINT32   TiltActive   : 1;       // 1 = active, 0=off
   UINT32   TiltCurrent_A: 6;       // I  = #/63   (1 to 0)
   UINT32   TiltSupply_V : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltComp_mm  : 6;       // mm = #      (63 to 0)
   UINT32   TiltLeak_V   : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltTemp_C   : 6;       // C = # (63 to 0)

   UINT16	nFaultEn;		         // Each bit is the status of a fault see ICDStructFaultCode
	// current CFG settings
	ICDStructScanConfig_v1	m_ScanCFG;

} ICDStructStatus_v1;

typedef struct
{
	UINT8		version;
	UINT16	nFaultCode;		         // Each bit is the status of a fault see ICDStructFaultCode
	UINT16	lastErrorNo;            // Error number that occurred

	UINT16	scanInOperation   :1;   // 0 = Standby,    1 = Scanning
	UINT16	nAutoModeStatus	:1;   // 0 = OFF,        1 = ON
	UINT16	nLaserStatus		:1;   // 0 = OFF,        1 = ON
	UINT16	nPitchRollStatus  :1;   // 0 = OFF,        1 = ON
	UINT16	bSystemInitialized:1;   // 0 = OFF,        1 = ON
	UINT16	nPPSGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nZdaGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nOCBGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nCTDGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nICloudGood       :1;   // 0 = Off/Failed, 1 = good
	UINT16	nRTVGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	nNavGood          :1;   // 0 = Off/Failed, 1 = good
	UINT16	gain			      :4;   // 1-12 Laser Gain Current

	INT16		azScannerPos_deg;	      // deg = #*30/32767
	INT16		elScannerPos_deg;	      // deg = #*30/32767 for spinners it is Hz = #*50/32767
	UINT8		nScansCompletePcnt;	   // % = # ( 0 to 100)
	INT8		PBTemperature_C;		   // C = #/2 (+64 to -64)
	INT8		DiodeTemp_C;		      // C = #/2 (+64 to -64)
	INT8		CryTemp_C;		         // C = #/2 (+64 to -64)
	INT8		HeatSinkTemp_C;		   // C = #/2 (+64 to -64) Electronics
	INT8		LsrHeatSinkTemp_C;	   // C = #/2 (+64 to -64) Laser
	INT8		DigTemp_C;		         // C = #/2 (+64 to -64)
	INT8		DigCOSTemp_C;           // C = #/2 (+64 to -64) 
   INT8		OCBTemp_C;		         // C = #/2 (+64 to -64)
	INT8		OPBTemp_C;		         // C = #/2 (+64 to -64)
	UINT8		Voltage5;		         // V = #*6/256
	UINT8		Voltage3;		         // V = #*4/256
	UINT8		Humidity;		         // % = #*100/256
	UINT8    ScanPatternType;    	   // 0-5       
   INT16		pitch_deg;		         // deg = #*90/32767
	INT16		roll_deg;		         // deg = #*90/32767
	INT8		pitchRoll_temperature; 	// C = #/2 (+64 to -64)
	INT8		CTD_temperature_c;     	// C = #/2 (+64 to -64)
	UINT16	CTD_salinity_psu;	      // PSU = #*42/65535
	UINT16	CTD_pressure_dbar;   	// dBar = #/13 (5041.15 to 0)
	INT8		PBTemperature2_C;      	// C = #/2 (+64 to -64)
	UINT8		PBHumidity;           	// % = #*100/256
   
   ///////////////////////////////////////////////////////////
   // Unique status items for version 1 (order is after v0)
   UINT8    CommMode:     4;        // mode of the comm thread (pan, wait, scan)
   UINT8    EyeSafe:      1;        // Last eyesafe check passed
   UINT8    PanTiltModel: 2;        // None, Sidus pantilt, Sidus pan, 3D PanTilt
   UINT8    Spare:        1;
   
   UINT8    nPanTiltStatus;         // MSB Error        = bit 8 
                                    //     Move done    = bit 7
                                    //     Moving       = bit 6
                                    //     Homed        = bit 5
                                    //     Homing       = bit 4
                                    //     Initialized  = bit 3
                                    //     Initializing = bit 2
                                    // LSB Power On     = bit 1
   UINT8    ptMode;                 // See table
   UINT16   ptSwitches;             // MSB Stall state                  = bit 15 
                                    //     Error state                  = bit 14
                                    //     Received initialization cmds = bit 13
                                    //     Received Configuration       = bit 12
                                    //     Power enabled                = bit 11
                                    //     Initialized                  = bit 10
                                    //     Powered on                   = bit 9	 
                                    //     Accepted Stop command        = bit 8	 
                                    //     Request Stop                 = bit 7	 
                                    //     Tilt  stable                 = bit 6	 
                                    //     Pan stable                   = bit 5	 
                                    //     Reading position             = bit 4	 
                                    //     Homed                        = bit 3	 
                                    //     Initializing                 = bit 2	 
                                    //     Serial busy                  = bit 1	 
                                    // LSB Emergency Stop               = bit 0	 
   INT16	   PanPos_deg;	            // deg = #*360/32767
   UINT32   PanBrake    : 1;        // 1 = on, 0 = off
   UINT32   PanActive   : 1;        // 1 = active, 0=off
   UINT32   PanCurrent_A: 6;        // I  = #/63   (1 to 0)
   UINT32   PanSupply_V : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanComp_mm  : 6;        // mm = #      (63 to 0)
   UINT32   PanLeak_V   : 6;        // V  = #*4/63 (4 to 0)
   UINT32   PanTemp_C   : 6;        // C = # (63 to 0)

   INT16  	TiltPos_deg;	         // deg = #*360/32767
   UINT32   TiltBrake    : 1;       // 1 = on, 0 = off
   UINT32   TiltActive   : 1;       // 1 = active, 0=off
   UINT32   TiltCurrent_A: 6;       // I  = #/63   (1 to 0)
   UINT32   TiltSupply_V : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltComp_mm  : 6;       // mm = #      (63 to 0)
   UINT32   TiltLeak_V   : 6;       // V  = #*4/63 (4 to 0)
   UINT32   TiltTemp_C   : 6;       // C = # (63 to 0)

   UINT16	nFaultEn;		         // Each bit is the status of a fault see ICDStructFaultCode
	// current CFG settings
	ICDStructScanConfig 	m_ScanCFG; // v5

} ICDStructStatus;

typedef struct
{
	ICDStructPacketHeader	sHeader;
	ICDStructScanConfig		nData;		   // Config structure to save or to start running. 
	UINT16			         nCheckSum;
} ICDScanCFGPacket; // v4

typedef struct
{
	ICDStructPacketHeader	sHeader;
	ICDStructScanConfig_v1	nData;		   // Config structure to save or to start running. 
	UINT16			         nCheckSum;
} ICDScanCFGPacket_v1;

typedef struct
{
	ICDStructPacketHeader	sHeader;
	ICDStructRTVConfig		nData;		// Config structure to save. sure. 
	UINT16			         nCheckSum;
} ICDRtvCFGPacket;


typedef struct
{
	ICDStructPacketHeader	sHeader;
	UINT16			         nCommand;	// command set 0x0001 for start, 0x1000 for stop
	UINT16			         nCfgNumber;	// nConfigNumber 0 for last config received.
	UINT16			         nCheckSum;
} ICDOperationPacket;

typedef struct
{
	ICDStructPacketHeader	sHeader;
   UINT16			         nErrorCode;
   UINT8			            nLevel;
	char			            strText[256];	 // max size is 256, last value is always zero.
	UINT16			         nCheckSum;
} ICDTextPacket;

typedef struct					// Only needed if the CTD is not coming from INS.
{
	ICDStructPacketHeader   sHeader;
	float			            temperature_c;
	float			            salinity_psu;
	float			            pressure_dbar;
	UINT16			         nCheckSum;
} ICDCTDPacket;

typedef struct
{
	ICDStructPacketHeader	sHeader;
	ICDStructStatus	      sStatus;	    // Upon the heartbeat request, small Status returned
	UINT16			         nCheckSum;
} ICDStatusPacket;

typedef struct					// Only needed if the CTD is not coming from INS.
{
	ICDStructPacketHeader   sHeader;
	UINT16			         PacketId;
	UINT16			         nCheckSum;
} ICDAcknowledgePacket;

typedef union {
	UINT16 word;
	struct {
   UINT16  nFaultOCBTemp_C     :1;	
	UINT16  nFaultOCBHumidity   :1;	
	UINT16  nFaultPBTemp1_C     :1;	
	UINT16  nFaultPBTemp2_C     :1;

	UINT16  nFaultPbHumidity    :1;	
	UINT16  nFaultDigTemp_C     :1;	
	UINT16  nFaultLaserHsTemp_C :1;
   UINT16  nFaultOpbTemp_C     :1;

   UINT16  nFaultPTSupply_V    :1;
   UINT16  nFaultPTCurrent_A   :1;
   UINT16  nFaultPTLinearComp  :1;
   UINT16  nFaultPTLeak_V      :1;

   UINT16  nFaultPanTemp_C     :1;
   UINT16  nFaultTiltTemp_C    :1;
   UINT16  nFaultWatchdog      :1;	
   UINT16  nFaultMinDepth      :1;
   } bits;
} ICDStructFaultCode;



// ******************************************************************************** 
// ** IDCScanCfgPacket class definition to communicate scan configuration data
// ******************************************************************************** 
class IDCScanCfgPacket : public Packet
{
public:

	IDCScanCfgPacket() : Packet()
	{ 
      ResetHdr();
	}
	~IDCScanCfgPacket(){}

   // take old def and populate newer one.
   void Set( ICDStructStatus_v1     *pStatus ) { TranslateICDStructScanConfigNew(&m_StructScanCfg, &pStatus->m_ScanCFG); }
   void Set( ICDStructScanConfig_v1 *pStruct ) { TranslateICDStructScanConfigNew(&m_StructScanCfg, pStruct); }

	void Set( ICDStructScanConfig *pStruct ) { memcpy( DataStart(), pStruct, DataSize() );  }
	void Get( ICDStructScanConfig *pStruct ) { memcpy( pStruct, DataStart(), DataSize() );  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return sizeof( ICDStructScanConfig  ) + 2; }
	void *HdrStart()    { return &m_PacketHdr; }
	void *DataStart()   { return &m_StructScanCfg; }
	UINT16 DataSize()   { return sizeof( ICDStructScanConfig ); }
   void  ResetHdr() 
   {
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_SCANNER_CFG;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
   }
	ICDStructPacketHeader	m_PacketHdr;
	ICDStructScanConfig		m_StructScanCfg;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCScanCfgPacket class definition to communicate scan configuration data
// ** ICDStructScanConfig_v1 data type
// ******************************************************************************** 
class IDCScanCfgPacket2 : public Packet
{
public:

	IDCScanCfgPacket2() : Packet()
	{ 
      ResetHdr();
	}
	~IDCScanCfgPacket2(){}
   // take newer def and populate older one.
   void Set( ICDStructStatus     *pStatus ) { TranslateICDStructScanConfigOld(&m_StructScanCfg, &pStatus->m_ScanCFG); }
   void Set( ICDStructScanConfig *pStruct ) { TranslateICDStructScanConfigOld(&m_StructScanCfg, pStruct); }

	void Set( ICDStructScanConfig_v1 *pStruct ) { memcpy( DataStart(), pStruct, DataSize() );  }
	void Get( ICDStructScanConfig_v1 *pStruct ) { memcpy( pStruct, DataStart(), DataSize() );  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return sizeof( ICDStructScanConfig_v1  ) + 2; }
	void *HdrStart()    { return &m_PacketHdr; }
	void *DataStart()   { return &m_StructScanCfg; }
	UINT16 DataSize()   { return sizeof( ICDStructScanConfig_v1 ); }
   void  ResetHdr() 
   {
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_SCANNER_CFG2;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
   }
	ICDStructPacketHeader	m_PacketHdr;
	ICDStructScanConfig_v1	m_StructScanCfg;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCRtvCfgPacket class definition to communicate rtv configuration data
// ******************************************************************************** 
class IDCRtvCfgPacket : public Packet
{
public:

	IDCRtvCfgPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_RTV_CFG;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCRtvCfgPacket(){}

	void Set( ICDStructRTVConfig *pStruct ) { memcpy( DataStart(), pStruct, DataSize() );  }
	void Get( ICDStructRTVConfig *pStruct ) { memcpy( pStruct, DataStart(), DataSize() );  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return sizeof( ICDStructRTVConfig  ) + 2; }
	void *HdrStart()    { return &m_PacketHdr; }
	void *DataStart()   { return &m_StructRtvCfg; }
	UINT16 DataSize()   { return sizeof( ICDStructRTVConfig ); }

	ICDStructPacketHeader	m_PacketHdr;
	ICDStructRTVConfig		m_StructRtvCfg;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCOperatePacket class definition to communicate starting or stopping a scan
// ******************************************************************************** 
class IDCOperatePacket : public Packet
{
public:

	IDCOperatePacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_OPERATE;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCOperatePacket(){}

	void Set( ICDOperationPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	void Get( ICDOperationPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 4 + 2; }
	void *HdrStart()    { return &m_PacketHdr; }
	void *DataStart()   { return &nCommand; }
	UINT16 DataSize()   { return 4; }

	ICDStructPacketHeader	m_PacketHdr;
   UINT16			         nCommand;	
   UINT16			         nCfgNumber;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCCtdPacket class definition to communicate CTD data
// ******************************************************************************** 
class IDCCtdDataPacket : public Packet
{
public:

	IDCCtdDataPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_CTD;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCCtdDataPacket(){}

	void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 12 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &temperature_c; }
	UINT16 DataSize()   { return 12;             }

	ICDStructPacketHeader	m_PacketHdr;
	float			            temperature_c;
	float			            salinity_psu;
	float			            pressure_dbar;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCLaserPacket class definition to communicate MBARI laser data ... 
// **   TBD: is there a need to use CCI commands with MBARI ... maybe with SL5 or 6?
// ******************************************************************************** 
class IDCLaserPacket : public Packet
{
public:

	IDCLaserPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_LASER;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCLaserPacket(){}

	//void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	//void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( )  { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 9 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &LaserPercent; }
	UINT16 DataSize()   { return 9;             }

	ICDStructPacketHeader	m_PacketHdr;
   float                   LaserPercent;        //  MBARI cmd, in 10th of percent
   float                   AttenuatorPercent;   //  MBARI cmd
   UINT8                   PowerOn;             // 1=on, 0=off (quick on/off) option.
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCDetBiasPacket class definition to communicate MBARI laser data ... 
// **   TBD: is there a need to use CCI commands with MBARI ... maybe with SL5 or 6?
// ******************************************************************************** 
class IDCDetBiasPacket : public Packet
{
public:

	IDCDetBiasPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_DETBIAS;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCDetBiasPacket(){}

	//void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	//void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( )  { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 12 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &BiasGreen; }
	UINT16 DataSize()   { return 12;             }

	ICDStructPacketHeader	m_PacketHdr;
   float                   BiasGreen;           //  MBARI cmd, Green reciever 20 to 32.75 volts of bias
   float                   BiasRed1 ;           //  MBARI cmd, Red1  reciever 20 to 32.75 volts of bias
   float                   BiasRed2 ;           //  MBARI cmd, Red2  reciever 20 to 32.75 volts of bias
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCPwrModePacket class definition to communicate Power levels for system 
// ******************************************************************************** 
class IDCPwrModePacket : public Packet
{
public:

	IDCPwrModePacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_PWR_MODE;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCPwrModePacket(){}

	//void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	//void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( )  { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 1+2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &nMode; }
	UINT16 DataSize()   { return 1;             }

	ICDStructPacketHeader	m_PacketHdr;
   UINT8                   nMode;           //  MBARI cmd (and others). 0=low power mode, 1=normal mode.
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCAttenuatorPacket class definition to communicate MBARI Attenuator data ... 
// **   TBD: is there a need to use CCI commands with MBARI ... maybe with SL5 or 6?
// ******************************************************************************** 
class IDCAttenuatorPacket : public Packet
{
public:

	IDCAttenuatorPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_ATTEN;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCAttenuatorPacket(){}

	//void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
	//void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( )  { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 15 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &LaserPercent; }
	UINT16 DataSize()   { return 15;             }

	ICDStructPacketHeader	m_PacketHdr;
   float                   LaserPercent;        //  MBARI cmd, in 10th of percent... TBD- removed for now.
   float                   AttenuatorPercent;   //  MBARI cmd
   float                   AttenuatorAngleLvl;  //  MBARI cmd
   UINT8                   AttenuatorByLine;    //  MBARI cmd, 1=true, 0=false (default)
   UINT16                  AttenuatorAngle_deg; //  MBARI cmd, 0-360
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** ICDLaserTecPacket class definition to communicate MBARI LASER TEC data ... 
// **   TBD: is there a need to use CCI commands with MBARI ... maybe with SL5 or 6?
// ******************************************************************************** 
class ICDLaserTecPacket : public Packet
{
public:

   ICDLaserTecPacket() : Packet()
   { 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_LSRTEC;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
   }
   ~ICDLaserTecPacket(){}

   //void Set( ICDCTDPacket *pStruct ) { memcpy( HdrStart(), pStruct, Length() +2);  }
   //void Get( ICDCTDPacket *pStruct ) { memcpy( pStruct, HdrStart(), Length() +2);  }

   UINT16 GetPktId( )  { return m_PacketHdr.nPacketID;  }
   UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
   UINT16 DataLength() { return 6 + 2;         }
   void *HdrStart()    { return &m_PacketHdr;   }
   void *DataStart()   { return &LaserTEC_C; }
   UINT16 DataSize()   { return 6;           }

   ICDStructPacketHeader	m_PacketHdr;
   float                   LaserTEC_C;    //  MBARI cmd, in 10th of percent... TBD- removed for now.
   UINT8                   LaserTECOn;    //  MBARI cmd, 1=true, 0=false
   UINT8                   LaserTECAuto;  //  MBARI cmd, 1=true in auto mode, 0=false
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCAckPacket class definition to communicate CTD data
// ******************************************************************************** 
class IDCAckPacket : public Packet
{
public:

	IDCAckPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_ACK;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCAckPacket(){}

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 2 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &PacketId; }
	UINT16 DataSize()   { return 2;             }

	ICDStructPacketHeader	m_PacketHdr;
   UINT16			         PacketId;
   UINT16			         nCheckSum;
};
// ******************************************************************************** 
// ** IDCAckPacket class definition to communicate CTD data
// ******************************************************************************** 
class IDCStatusReqPacket : public Packet
{
public:

	IDCStatusReqPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_STATUS_REQ;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2; // which status version to return...
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();

      nRequestVer = CCI_VERSION_5;
	}
	~IDCStatusReqPacket(){}

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return 1 + 2;         }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &nRequestVer; }
	UINT16 DataSize()   { return 1;             }

	ICDStructPacketHeader	m_PacketHdr;
   UINT8			            nRequestVer; // which status version to return. 0 (basic) or 1 (which has Pan/Tilt)
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCStatusPacket class definition to communicate status data
// ******************************************************************************** 
class IDCStatusPacket : public Packet
{
public:

	IDCStatusPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_STATUS_TLM;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCStatusPacket(){}

   // set newer version with older one.
   void Set( ICDStructStatus_v1     *pStatus ) { TranslateICDStructScanConfigNew(&m_Status.m_ScanCFG, &pStatus->m_ScanCFG); }
   void Set( ICDStructScanConfig_v1 *pStruct ) { TranslateICDStructScanConfigNew(&m_Status.m_ScanCFG, pStruct); }
	void Set( ICDStructStatus *pStruct ) { memcpy( DataStart(), pStruct, DataSize());  }
	void Get( ICDStructStatus *pStruct ) { memcpy( pStruct, DataStart(), DataSize());  }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return DataSize() + 2; }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &m_Status;      }
	UINT16 DataSize()   { return sizeof(ICDStructStatus); }

	ICDStructPacketHeader	m_PacketHdr;
	ICDStructStatus         m_Status;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCStatusPacket class definition to communicate status data
// ******************************************************************************** 
class IDCStatusPacket2 : public Packet
{
public:

	IDCStatusPacket2() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_STATUS_TLM2;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;
      m_PacketHdr.nDataSize      = DataLength();
	}
	~IDCStatusPacket2(){}
   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
   // set older version with newer one.
   void Set( ICDStructStatus     *pStatus ){ TranslateICDStructScanConfigOld(&m_Status.m_ScanCFG, &pStatus->m_ScanCFG); }
   void Set( ICDStructScanConfig *pStruct ){ TranslateICDStructScanConfigOld(&m_Status.m_ScanCFG, pStruct); } 
	
	void Set( ICDStructStatus_v1 *pStruct ) { memcpy( DataStart(), pStruct, DataSize());  }
	void Get( ICDStructStatus_v1 *pStruct ) { memcpy( pStruct, DataStart(), DataSize());  }

	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return DataSize() + 2; }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &m_Status;      }
	UINT16 DataSize()   { return sizeof(ICDStructStatus_v1); }

	ICDStructPacketHeader	m_PacketHdr;
	ICDStructStatus_v1      m_Status;
   UINT16			         nCheckSum;
};

// ******************************************************************************** 
// ** IDCTextMsgPacket class definition to communicate CTD data
// ******************************************************************************** 
class IDCTextMsgPacket : public Packet
{
public:
   enum {
      MAX_TEXT_SIZE = 271
   };
	IDCTextMsgPacket() : Packet()
	{ 
      m_PacketHdr.nAlignmentCode = HDR_CODE_ICD;
      m_PacketHdr.nPacketID      = PACKET_CC_TEXT;
      m_PacketHdr.nVersion       = HDR_VERSION_ICD_V2;
      m_PacketHdr.nHeaderSize    = PacketHdr::HDR_SIZE;

      m_nErrorCode = 0;
      m_nLevel     = 0;
      memset(m_strText, 0, 258);
      m_iMsgSize       = 0;
      m_PacketHdr.nDataSize      = DataLength(); // after m_iMsgSize set
	}
	~IDCTextMsgPacket(){}

	void Set(const char *pMsg ) 
   { 
      m_iMsgSize = strlen(pMsg);
      m_iMsgSize = (m_iMsgSize > 254? 254:m_iMsgSize);
      memcpy( m_strText, pMsg, m_iMsgSize);
      
      m_strText[m_iMsgSize] = 0; // zero end.
      m_iMsgSize++;
      if (m_iMsgSize%2 != 0) 
      {   m_iMsgSize++; m_strText[m_iMsgSize] = 0;  }
      pCheckSum = (UINT16*)(&(m_strText[m_iMsgSize+1]));
      m_PacketHdr.nDataSize = DataLength();
   }
	void Get( char *pMsg ) { memcpy( pMsg, m_strText, m_iMsgSize+1);  }
   void SetChecksum( UINT16 Chksum ) 
                          { m_strText[m_iMsgSize+1] = Chksum&(0xff); 
                            m_strText[m_iMsgSize+2] = Chksum>>8;    }

   UINT16 GetPktId( ) { return m_PacketHdr.nPacketID;  }
	UINT16 Length()     { return sizeof( ICDStructPacketHeader) + DataSize(); }
   UINT16 LengthWSum() { return Length() +2; } // for "send" - checksum
	UINT16 DataLength() { return DataSize() + 2; }
	void *HdrStart()    { return &m_PacketHdr;   }
	void *DataStart()   { return &m_nErrorCode;  }
	UINT16 DataSize()   { return 4+m_iMsgSize;   }
   // set parameters based on header info... after reading packet
   void SetFromHeader(){ m_iMsgSize = m_PacketHdr.nDataSize - 2 - 4;
                         pCheckSum = (UINT16*)(&(m_strText[m_iMsgSize+1]));
                       }

	ICDStructPacketHeader	m_PacketHdr;
   UINT16			         m_nErrorCode;
   UINT8			            m_nLevel;
   char			            m_strText[258];
   UINT16*			         pCheckSum;

   int                     m_iMsgSize; 
   // max packet size is 258 + 3 + 10 = 271
};


typedef struct
{
	UINT16		nAlignmentCode;                
	UINT16		nPacketID;
	UINT16	   nVersion;  // =HDR_VERSION_ICD for original, =HDR_VERSION_ICD_V1 for Pan version	
   //UINT32		nDataSize; // Bytes old def.
   UINT16		nHeaderSize;// Bytes
	UINT16		nDataSize;  // Bytes
} ICDStructPacketHeader;

// ******************F************************************************************** 
// ** Comm2::CheckSum(void* pData, UINT16 size)
// ** Calculate a checksum over the data specified
// ******************************************************************************** 
UINT16 Comm2::CheckSum(void* pData, UINT16 size_bytes)
{
	UINT8 *p_data = (UINT8*)(pData);
	UINT16 n16Checksum=0; UINT16 n16Check;
	for ( int i=0; i < size_bytes ; i+=2 )
	{	n16Check=0;
		n16Check=(UINT8)p_data[i];
      n16Check = n16Check<<8;
		if ( (i+1) < size_bytes ) // index can not == size_bytes (outside of define)
         n16Check +=(UINT8)p_data[i+1];
		n16Checksum+=n16Check;
	}
	return n16Checksum;
}


// ******************************************************************************** 
// ** Packet header class definition
// ** All comms packets contain a packet header, to describe packet type, size,
// ** and other transmission items.
// ******************************************************************************** 
class PacketHdr
{
public:
	enum
	{
		// packet Hdr constants
		HDR_VERSION					 = 0x0002, // ==HDR_VERSION_ICD_V2
		HDR_TAG						 = 0x3DF0,
		HDR_SIZE						 = 10
	};

	PacketHdr();
	PacketHdr( UINT16 nPacketType, UINT16 nSizeDataBytes=0 );
	~PacketHdr(void){};

	void SetPacket( UINT16 nPacketType, UINT16 nSizeDataBytes );
   void SetSize( UINT16 nSizeDataBytes ) { m_uDataSize = nSizeDataBytes; }

	void *DataStart()     { return &m_uAlignmentTag; }
	UINT16 AlignmentTag() { return m_uAlignmentTag; }
	UINT16 PacketID()     { return m_uPacketID; }
	UINT16 Version()      { return m_uVersion; }
	UINT16 HeaderSize()   { return m_uHeaderSize; }
	UINT16 DataSize()     { return m_uDataSize; }
	//UINT16 CRC()          { return m_uCRC; } // v1 only, was not used, will now match CCI header.
   // Support for CCI copies.
   void SetHeader(ICDStructPacketHeader* pHdr) {
      pHdr->nAlignmentCode = m_uAlignmentTag;
      pHdr->nPacketID      = m_uPacketID;
      pHdr->nVersion       = m_uVersion;
      pHdr->nHeaderSize    = m_uHeaderSize;
      pHdr->nDataSize      = m_uDataSize;
   }
//protected:
	// defines order of elements in HDR
	UINT16		m_uAlignmentTag;
	UINT16		m_uPacketID;
	UINT16		m_uVersion;
	UINT16		m_uHeaderSize;
	UINT16		m_uDataSize;
	//UINT32		m_uCRC;
};

// ******************************************************************************** 
// ** Packet base class virtual definition
// ******************************************************************************** 
class Packet
{
public:
	Packet(){}
	~Packet(){}

	virtual void SetHdr( PacketHdr *pHdr ){}
   virtual UINT16 GetPktId( ) = 0;
	virtual UINT16 Length() = 0;
   virtual UINT16 LengthWSum() = 0; // must have send size.
	virtual void *HdrStart() = 0;
	virtual void *DataStart() = 0;
};

