#ifndef REP_FPGA_INTERFACE_H
#define REP_FPGA_INTERFACE_H

#include "FakeIDD.h"

//FPGA programming
struct RepRawTimetag
{
    uint32_t raw_timetag;
    uint32_t batch_id;
};

//Basic mode context
struct RepModeSettingData
{
    RepRawTimetag btt;

    uint32_t master_mode;
    uint32_t master_submode;
    uint32_t expand;

    uint32_t mode;
    uint32_t stby;
    uint32_t radiate;

    uint32_t range_scale_code;
    uint32_t range_scale_meters;
};


//Navigation data
struct RepBasicNavigationData
{
    RepRawTimetag btt;

    float platform_azimuth;
    float vx;
    float vy;
    float pitch;
    float roll;

    float altitude;
};



//Target Info
struct RepTgtInfo
{
public :

    //## type TgtKind_t
    enum TgtKind_t
    {
        TGT_KIND_UNK = 0,
        TGT_KIND_FRI = 1,
        TGT_KIND_FOE = 2,
        TGT_KIND_MIN = TGT_KIND_UNK,
        TGT_KIND_MAX = TGT_KIND_FOE
    };

    RepRawTimetag btt;

    float altitude_m;		//## attribute altitude_m

    float azimuth_rad;		//## attribute azimuth_rad

    int bar;		//## attribute bar

    TgtKind_t kind;		//## attribute kind

    float range_m;		//## attribute range_m

    float velocity_ms;		//## attribute velocity_ms
};

struct RepResultTargets
{
    enum { max_tgt = 8};
    unsigned int tgt_num;

    RepTgtInfo tgt[max_tgt];
};


//DSP Messages
struct RepDspDestinationAddress
{
        uint32_t header_address;
        uint32_t header_dst_id;
        uint32_t ch_map;
        uint32_t ch_address[12];
        uint32_t ch_dst_id[12];
        uint32_t doorbell_code;
        uint32_t doorbell_dst_id;
};

struct RepDspSignalHeader
{
    RepModeSettingData basicMode;
    uint32_t dsp_mode;

    uint32_t test_code[2];
    uint32_t simulation_code[2];

    RepBasicNavigationData navData;

    uint32_t rbins;
    float rbin_meters;

    //Antenna
    uint32_t bar_number;

    float azimuth;
    float elevation;

    int32_t ant_direction;
    uint32_t ant_progress;
    float az_limit_left;
    float az_limit_right;

    uint32_t spare[8];
};

typedef RexMessageHeaderPayloaded<RepDspSignalHeader> RepDspSignalHeaderMessage;

struct RepDspResultsData
{
    RepResultTargets targets;
};

typedef RexMessageHeaderPayloaded<RepDspResultsData> RepDspResultsMessage;

#if 0
struct RepDspRawSweepSamples
{
    enum { sweep_max_rbins=4096};
    unsigned int valid;
    float azimuth;
    unsigned int samples;
    unsigned int spare[2];

    uint8_t data[sweep_max_rbins];
};

struct RepDspImageDescriptor
{
    uint32_t valid;
    uint32_t clear;

    uint32_t dx;
    uint32_t dy;
    uint32_t ox;
    uint32_t oy;
    uint32_t rows;
    uint32_t stride;
};

struct RepDspRawSweepHeader
{
    uint32_t mode;

    enum sc_mode_t { sc_disable=0, sc_test=1, sc_polar, sc_image, sc_oscilloscope};
    uint32_t sc_mode;

    uint32_t rbins;
    float rbin_meters;

    //Antenna
    uint32_t bar_number;

    float scan_center;
    float azimuth;
    float elevation;

    int32_t ant_direction;
    uint32_t ant_progress;
    float az_limit_left;
    float az_limit_right;

    float range_scale;

    float platform_azimuth;
    float vx;
    float vy;

    float ant_u;
    float ant_v;

    int bar_progress;
    int frame_progress;

    uint32_t spare[6];

    RepDspImageDescriptor image_descriptor;
};

struct RedDspRawSweepRadials
{
    enum {max_radials=32};
    unsigned int valid_radials;
    RepDspRawSweepSamples sweep[max_radials];
};
struct RepDspRawSweepData
{
    enum {msg_enable_marker=0x12345678};
    RepDspRawSweepHeader header;
    unsigned int msg_enable;
    char msg[4][64];
    RedDspRawSweepRadials radials; //RepDspRawSweepSamples sweep;
};
#endif
struct RepFpgaProgramData
{
    RepDspDestinationAddress dstAddresses;

    uint32_t batch_mode;
    uint32_t batch_time_us;
    uint32_t prf;
    uint32_t rbins;

    RepDspSignalHeader dspHeader;
};

typedef RexMessageHeaderPayloaded<RepFpgaProgramData> RepFpgaProgramDataMessage;


struct RepFpgaSignalHeaderData
{
    RepDspSignalHeader dspHeader;
    uint32_t acq_channel;	//sum, guard, delta,...
        enum { acq_ch_sum=1, acq_ch_guard=2, acq_ch_delta_az=4, acq_ch_delta_el=8};

    uint32_t signal_format;
        enum { sig_fmt_sim_targets=0x100, sig_fmt_sweep};
};

struct RepFpgaSimulationTargetsData
{
    RepFpgaSignalHeaderData fpgaHeader;

    RepResultTargets simTargets;
};

typedef RexMessageHeaderPayloaded<RepFpgaSimulationTargetsData> RepFpgaSimulationTargetsMessage;

struct RepFpgaSimulationSweepSamples //: public RepDspRawSweepSamples
{
    enum { sweep_max_rbins=2048};
    uint8_t data[sweep_max_rbins];

    //enum { sweep_max_rbins=2048};
    //uint8_t data[sweep_max_rbins];
};

struct RepFpgaSimulationSweepData
{
    RepFpgaSignalHeaderData fpgaHeader;

    RepFpgaSimulationSweepSamples simSweep;
};

typedef RexMessageHeaderPayloaded<RepFpgaSimulationSweepData> RepFpgaSimulationSweepMessage;

#define FakeFpgaTargetsMessage RepFpgaSimulationTargetsMessage
#define FakeRepPgmMessage RepFpgaProgramDataMessage
#define FakeMessageHeader RexMessageHeader

struct RepFpgaSignal
{
    RepFpgaSignalHeaderData fpgaHeader;
    uint8_t data[2048];
};

struct FakeFpgaMessage
{
    FakeMessageHeader msgHeader;
    RepFpgaSignal fpgaSignal;
};

#include "rex_udp_tunnelling.h"

#if 0
///*****************************************
#include <stdint.h>

//Fragmentation Protocol on rex_msg_flow_control_t word
//  1. TX: First TX message alaways not jumbo, sender jumbo capacity, ack window don't care (0)
//  2. RX: First ACK always sent with receiver jumbo capacity and ack window
//  3. TX: send rest of message according with the min(jumbo_rx, jumbo_tx), waiting for acq only every rx ack_window messages
//  4. RX: receive and sent ACk every rx ack_window messages. If receive a new message with current_frag=0, drop  uncomplete message and restart
//There are more then one message on the "fly". A message is uniquely identified by:
//  (dst,src,mailboc,transaction_id)
//The fcs is relative to the channel id and is incremented for every message, regardless on the fragments and unique id

struct RexUdpMsgHeader2	//WARNING: please guarantee alignment
{
    enum msg_class_t { t_msg=0, t_memory_write=1, memory_read=2};
    enum marker_value_t { marker_begin = '!', marker_body='+', marker_end='-'};
    enum { msg_mtu=4*1024};
    enum { msg_frag_mtu=1400};

    struct flow_control_t
    {	//Warning: the bitfield must saek exactly 32bits
        unsigned int jumbo:	4;	//Jumbo packet support: size=1000*(jumbo+1), 0=default MTU (1500 other Ethernet, 4K over SRIO
        unsigned int ack_window: 6;	//max windows accepted for ACK. 0=ack only last

        unsigned int ack: 1;
        unsigned int ack_required: 1;

        unsigned int spare: 16;
    };

    //W0
    uint8_t marker_value;	//Always="!" - real type is msg_class_t
    uint8_t fmt;	//So far, always=0

    uint8_t src;
    uint8_t dst;

    //W1
    uint8_t op;	//0..127: op code, bit7=ack flag
    uint8_t msg_class;

    uint8_t transaction_id;
    uint8_t fcs;	//frame control sequence

    //W2
    uint32_t mailbox;	//This can be a mailbox+letter or a memory address (destination or source)
    uint32_t source_address; //for memory read operation
    //uint8_t letter;
    uint32_t doorbell;

    //W4
    flow_control_t flow_control;

    uint32_t total_message_size;

    uint32_t total_frags;
    uint32_t current_frags;

    uint8_t spare;
    uint8_t extsize_bytes;		//size, in types, to skip for the payload

    uint16_t payload_size_bytes;

    marker_value_t marker() const { return static_cast<marker_value_t>(marker_value);}
    msg_class_t messageClass() const { return static_cast<msg_class_t>(msg_class);}

    bool markerValid() const { return marker_value<=static_cast<uint8_t>(marker_end);}

    void setSize(unsigned int bytes)
    {
        total_message_size=bytes;
        total_frags=(bytes+(msg_frag_mtu-1)) / msg_frag_mtu;
        current_frags=0;
        payload_size_bytes=0;
    }
};

template<typename T_> struct RexUdpMsgHeaderT2
{
    typedef T_ payload_t;

    RexUdpMsgHeader2 header;

    payload_t payload;

    void setSize() { header.setSize(sizeof payload);}

};
//-------------------------------------------
#endif

#define RexUdpMsgHeaderT2 RexUdpMsgHeaderT
#define RexUdpMsgHeader2 RexUdpMsgHeader

namespace grifo_inet
{

enum port_id_t
{
    rex_control_port=50000,

    rex_interrupts_emulation=50010,

    rex_dsp0=52010,

    rex_ext_tgt_sim=52200,

};
}

enum iemul_id_t
{
    iemul_none=0,

    iemul_timetag_synch,
    iemul_batch

};

struct iemul_info_t
{
    uint32_t timetag;
    uint32_t tgt_mask;
    uint32_t intr_mask;	//see iemul_id_t
    uint32_t even_info;
    uint32_t spare[32];
};

#if 0
//----------------
union raw_batchtag_t {
  enum { tt_part=0, batch_part=1, total_parts=2};
  uint32_t d[total_parts];
};

typedef raw_batchtag_t RexBatchTag;
//-----------------------------
struct FakeMessageHeader
{
    uint32_t marker;
    uint32_t version;
    uint32_t len;
    uint32_t spare;	//round to multiple of 64bits
};
//------------------------------
struct FakeDspSignalHeader
{
    RexBatchTag btt;

    uint32_t mode;
    uint32_t stby;

    uint32_t rbins;
    float rbin_meters;

    //Antenna
    uint32_t bar_number;

    float azimuth;
    float elevation;

    int32_t ant_direction;
    uint32_t ant_progress;
    float az_limit_left;
    float az_limit_right;

    float range_scale;

    float platform_azimuth;
    float vx;
    float vy;

    struct
    {
        int test_pattern;
    };
    uint32_t spare[32];
};

struct FakeDspSignalMessage
{
    FakeMessageHeader msgHeader;

    FakeDspSignalHeader dspHeader;
    uint32_t data[8];
};

/*
struct FakeRepPgmHeader
{
    RexBatchTag btt;

    uint32_t mode;
    uint32_t stby;

    uint32_t rbins;
    float rbin_meters;

    //Antenna
    uint32_t bar_number;

    float azimuth;
    float elevation;

    uint32_t ant_direction;
    uint32_t ant_progress;
    float az_limit_left;
    float az_limit_right;

    float range_scale;

    float platform_azimuth;
    float vx;
    float vy;

    struct
    {
        int test_pattern;
    };
    uint32_t spare[32];
};
*/

struct FakeRepPgmMessage
{
    FakeMessageHeader msgHeader;

    FakeDspSignalHeader dspHeader;
    uint32_t data[8];
};


//----
struct FpgaSweep
{
    unsigned int samples;
    uint8_t data[1024];
};

struct FakeFpgaMessage
{
    FakeMessageHeader msgHeader;
    FakeDspSignalHeader dspHeader;

    FpgaSweep sweep;
};

struct FakeFpgaMessage2
{
    //FakeMessageHeader msgHeader;
    uint8_t data[1024];
};

//------
struct FakeDspTgtInfo
{
public :

    //## type TgtKind_t
    enum TgtKind_t
    {
        TGT_KIND_UNK = 0,
        TGT_KIND_FRI = 1,
        TGT_KIND_FOE = 2,
        TGT_KIND_MIN = TGT_KIND_UNK,
        TGT_KIND_MAX = TGT_KIND_FOE
    };

    RexBatchTag btt;

    float altitude_m;		//## attribute altitude_m

    float azimuth_rad;		//## attribute azimuth_rad

    int bar;		//## attribute bar

    TgtKind_t kind;		//## attribute kind

    float range_m;		//## attribute range_m

    float velocity_ms;		//## attribute velocity_ms
};

struct FakeDspResultTargets
{
    enum { max_tgt = 8};
    unsigned int tgt_num;
    unsigned int align;
    FakeDspTgtInfo tgt[max_tgt];
};

struct FakeFpgaTargetsMessage
{
    FakeMessageHeader msgHeader;
    FakeDspSignalHeader sigHeader;
    FakeDspResultTargets dspTgts;
};
#endif

#endif // REP_FPGA_INTERFACE_H
