//============================================================================
/// Summary  : Reson 6046 Commands
/// Filename : Reson6046Commands.h
/// Author   : Reed Christeson, reed@bluefinrobotics.com
/// Project  : Reson 6046 Driver
/// Revision : 0.0
/// Created  : 2002.04.15
/// Modified : 2002.04.15
//============================================================================
// From RESON SeaBat 7k DATA FORMAT INTERFACE CONTROL DOCUMENT 
//      Draft Version 0.32


#ifndef _RESON6046PAYLOADCOMMANDS_H
#define _RESON6046PAYLOADCOMMANDS_H

// System Includes
#include <string.h>

// Framework Includes
#include "Syslog.h"
#include "Time.h"
#include "TimeIF.h"

// Reson Includes
#include "Reson6046DataTypes.h"
#include "Reson6046Utils.h"

const U32 MESSAGE_WRAPPER_SYNC_PATTERN = 0xFFFF0000;
const U16 NETWORK_FRAME_VERSION = 1;
const U16 DATA_RECORD_FRAME_VERSION = 1;
const U32 DATA_RECORD_FRAME_SYNC_PATTERN = 0x0000FFFF;

const I64 I64_NEG_1 = {0xFFFFFFFF,0xFFFFFFFF};
const I64 I64_0 = {0x00000000, 0x00000000};

// --- A3.8 Sensor ID ---
const U32 MultibeamSonar = 0x10;
const U32 SideScanImagingSonar = 0x20;
const U32 SubbottomProfiler = 0x30;
const U32 ForwardLookingImagingSonar = 0x40;
const U32 SingleBeamEchoSounder = 0x50;
const U32 VideoCamera = 0x60;
const U32 AttitudeSensor = 0x70;


// TCP and UDP Network Frame (NF)
struct Reson6046NetworkFrame
{
    U16 version; // fixed, 1
    U16 offset; // fixed, size of NF
    U32 totalPackets;
    // Uncomment totalRecords for Phase 2 6046 on Payload Computer
    //U16 totalRecords;
    // Uncomment transmissionIdentifier for Phase 2 6046 on Payload Computer
    //U16 transmissionIdentifier;
    U32 packetSize; // size of bytes in this packet, including header and data.
    // Uncomment totalSize for Phase 2 6046 on Payload Computer
    //U32 totalSize; // total size of bytes of all packets in transmission excluding network frame(s).
    U32 sequenceNumber; // sequential packet number (0 to N-1).
};
// DRF follows...

// Data Record Frame (DRF)
struct Reson6046DataRecordFrame
{
    U16 version; // version of this frame
    U16 offset; // offset in bytes from the start of the sync pattern to the data section.
    U32 syncPattern; // 0x0000FFFF
    U32 size; // Size in bytes of this record from start of version to end of checksum, including data.
    U32 optionalDataOffset; // offset in bytes to optional data from start of record (0 = no data).
    U32 optionalDataIdentifier; // identifier for optional field (0 = no data).
    T7K time7k; // Reson 7K time tag.
    // Uncomment reserved1 for Phase 2 6046 on Payload Computer
    //U16 reserved1; // reserved.
    U32 recordTypeIdentifier; // identifier for record type of embedded data.
    U32 deviceIdentifier; // identifier of the device that this data pertains.
    U16 subsystemIdentifier; // identifier for the device subsystem.
    U16 systemEnumerator; // system enumerator for identical systems in one installation (0 - N).
    U32 dataSetNumber; // data set number.
    U32 sequentialRecordCounter; // sequential record counter.
    I64 pointerRecordPrevious; // pointer to the previous record of the same type.
    I64 pointerRecordNext; // pointer to the next record of the same type.
    U16 flags; // bit field, bit 1 = valid checksum.
    // Uncomment reserved2 for Phase 2 6046 on Payload Computer
    //U16 reserved2; // reserved.
    // DYNAMIC DATA SECTION
    U32 checksum; // As off 2002.04.17, not used by reson.
};

// Record Type # 11000
struct Reson6046PayloadControllerCommand
{
    U32 fillerField;  // Hack, ICD is incorrect for Phase I.
    U32 sensorIndex;
    //U32 hostID;
    U32 commandID;
    U32 action; // this is U8 in the ICD V0.27
    U32 commandBytesToFollow;
    //Ascii Command Data Follows;
};

// Record Type # 11001
struct Reson6046PayloadControllerCommandAcknowledge
{
    U32 commandID;
    U32 sensorIndex;
    U32 commandStatus;
};

// Record Type # 11002
struct Reson6046PayloadControllerAlarmOrStatus
{
    I32 messageType;
    I32 mode;
    I32 messageID;
    U32 messageBytesToFollow;
    // Ascii Message Follows
};

// --- A3.5 Message Wrapper Definition ---   
struct Reson6046MessageWrapper
{
    U32 startSync;    // 0xFFFF0000
    U32 messageType;  // Describes the type of message.
    U32 messageID;    // Identification numbers.  Explicit numbers for each message type.
    U32 messageSize;
    // message N bytes, N must be a multiple of 8 bytes
    U32 checksum;
    U32 spare; // Spare field to maintain byte alignment.
};

// --- A3.7 Acknowledge Message ---
struct Reson6046AcknowledgeMessage
{
    F64 timeTag;     // Indicates when message was received.
    U32 eventNumber; // 0 = invalid message. Event numbers > 0 indicates valid messages.
    U32 spare;       // Spare field to maintain byte alignment.
};

// ### A4 Payload Setup ###

// --- A4.1 Payload Setup Message ---


// --- A4.2 Payload Setup Answer Message ---

// ### A5 Payload Mode / Status / BIT ###

// --- A5.1 Payload Mode Message
// Message ID = 0
struct PayloadModeMessage
{
    U32 mode;
    U32 spare;
};

// --- A5.2 Request Payload Status Message ---
// Message ID = 1
// !!! Empty Message !!!

// --- A5.3 Payload Status Message ---
// Message ID = 2
struct PayloadStatusMessages
{
    F64 timeTag;
    U32 eventNumber;
    U32 mode;
    BYTE bit[8];
};



struct Reson6046CommandStructure
{
    struct Reson6046NetworkFrame networkFrame;
    U32 sizeNetworkFrame;
    U32 sizeNetworkFrameAndData;
    struct Reson6046DataRecordFrame dataRecordFrame;
    U32 sizeDataRecordFrame;
    U32 sizeDataRecordFrameAndData;
    struct Reson6046PayloadControllerCommand plcCommandFrame;
    U32 sizePlcCommandFrame;
    U32 sizePlcCommandFrameAndData;
    unsigned char *nfPtr;
    unsigned char *drfPtr;
    unsigned char *plccfPtr;
    unsigned char *responsePtr;
};


/// ******* RESON 6046 COMMANDS *******
class Reson6046Commands
{
 public:
    // ***** Enumerations *****
    enum ShowRawDataTypes
    {
	None = 0,
	ShowFrameOnly = 1,
	ShowFrameAndData = 2,
	ShowDataOnly = 3
    };

    // --- A3.6 Message Types ---
    enum Reson6046MessageTypes 
    {
	AcknowledgeMessage = 0,
	PayloadSetup = 1,
	PayloadModeAndStatus = 2,
	SensorControl = 3,
	PayloadTime = 4,
	QualityControl = 5,
	PayloadAlarms = 6,
	PayloadTriggers = 7,
	SensorData = 0x10
    };

    enum Reson6046PayloadMessageIDs 
    {
	PayloadModeMessage = 0,
	RequestPayloadStatusMessage = 1,
	PayloadStatusMessage = 2 
    };
    
    // Page 10-11 ICD Reson 7K v0.35.
    enum Reson6046RecordTypeIdentifiers 
    {
	//...
	PayloadControllerCommand = 11000,
	PayloadControllerCommandAck = 11001,
	PayloadControllerAlarmAndStatus = 11002 
	//...
    };

    // Page 7 of 19 6046 Software Spec. 2002.05.01
    enum Reson6046PLCRemoteCommands
    {
	PLC_Command_Generic = 0, // %s
	PLC_Command_Logging = 1, // %d
	PLC_Command_Switch = 2,  // %s
	PLC_Command_Path = 3,
	PLC_Command_Version = 4,
	PLC_Command_Load = 5,
	PLC_Command_Save = 6,
	PLC_Command_Subscribe = 7,
	PLC_Command_Unsubscribe = 8,
	PLC_Command_Alarm = 9,
	PLC_Command_Status = 10,
	PLC_Command_Verbose = 11,
	PLC_Command_Reset = 12,
	PLC_Command_Shutdown = 13,
	PLC_Command_Modules = 14,
	PLC_Command_RunList = 15,
	PLC_Command_Add = 16,
	PLC_Command_Remove = 17,
	PLC_Command_Reserved1 = 18,
	PLC_Command_Reserved2 = 19,
	PLC_Command_TimeSync = 20,
	PLC_Command_Health = 21
    };

    enum Reson6046PLCRemoteCommandActions
    {
	PLC_Action_Unspecified = 0,
	PLC_Action_Set = 1,
	PLC_Action_Get = 2
    };

    // Page 63 ICD Reson 7K v0.35
    enum Reson6046DeviceIdentifiers
    {
	//...
	BlufinVehicleController = 11100
	//...
    };

    enum Reson6046SensorIndex
    {
	SensorIndexPLC = -1,
	//...
	SensorIndexEdgeTech = 11000,
	SensorIndexBluefin = 11100
	//...
    };


    // ***** Methods. *****
    Reson6046Commands();
    virtual ~Reson6046Commands();

    // Paload Controller Command Methods
    void initPlcCommandFrame();
    int setPlcCommandFrame(U32 sensorIndex,
			   U32 commandID,
			   U32 action,
			   char *command);
/*     int setPlcCommandFrame(U32 sensorIndex, */
/* 			   U32 commandID, */
/* 			   U32 action, */
/* 			   char *command, */
/* 			   U32 parameter); */
/*     int setPlcCommandFrame(U32 sensorIndex, */
/* 			   U32 commandID, */
/* 			   U32 action, */
/* 			   char *command, */
/* 			   F32 parameter); */
/*     int setPlcCommandFrame(U32 sensorIndex, */
/* 			   U32 commandID, */
/* 			   U32 action, */
/* 			   char *command, */
/* 			   char *parameter); */
    void displayPlcCommandFrame(U32 showFrame = None);
    unsigned int getSizePlcCommandFrameAndData() const
	{ return(cmdStruct.sizePlcCommandFrameAndData); }
    unsigned char *getPtrPlcCommandFrameAndData() const
	{ return(cmdStruct.plccfPtr); }

    // Data Record Frame methods.
    void initDataRecordFrame();
    int setDataRecordFrame( U32 recordTypeIdentifier,
			    U32 deviceIdentifier = 0,
			    U16 subsystemIdentifier = 0,
			    U16 systemEnumerator = 0,
			    U32 dataSetNumber = 0,
			    TimeIF::TimeSpec *setTime = NULL,
			    U32 checksum = 0,
			    U16 flags = 0, // no checksum at this time
			    U32 sequentialRecordCounter = 0,
			    //I64 pointerRecordPrevious,
			    //I64 pointerRecordNext,
			    U32 optionalDataOffset = 0,
			    U32 optionalDataIdentifier = 0);//,
    //U16 reserved1 = 0,
    //U16 reserved2 = 0);
    void displayDataRecordFrame(U32 showFrame = None) const;
    unsigned int getSizeDataRecordFrameAndData() const
	{ return(cmdStruct.sizeDataRecordFrameAndData); }
    unsigned char *getPtrDataRecordFrameAndData() const
	{ return(cmdStruct.drfPtr); }

    // Network Frame
    void initNetworkFrame();
    int Reson6046Commands::setNetworkFrame( //U16 transmissionIdentifier = 0,
					    U32 totalPackets = 1,
					    //U16 totalRecords = 1,
					    //U32 totalSize = 0,
					    U32 sequenceNumber = 0);
    void displayNetworkFrame(U32 showFrame = None ) const;
    unsigned int getSizeNetworkFrameAndData() const
	{ return(cmdStruct.sizeNetworkFrameAndData); }
    unsigned char *getPtrNetworkFrameAndData() const
	{ return(cmdStruct.nfPtr); }

    void showRawFrame(BYTE *framePtr, U32 size) const;

    // Fill out the 7K time structure.
    // If setTime == NULL, set 7k time to current time.
    void set7kTime(T7K *time7k, TimeIF::TimeSpec *setTime = NULL);

 private:
    Reson6046CommandStructure cmdStruct;
};

#endif
