#ifndef GRIFO_CORE_FW_DRIVER_H
#define GRIFO_CORE_FW_DRIVER_H

#include <stdint.h>

class GrifoCoreFwFunction
{   //A POD that can be statically initialized
public:
    typedef void (*function_driver_default_memory_initializer_t)(void*);

    enum
    {
        evet_invalid=0xFFFF
    };

    enum area_t {
        area_a,
        area_b,

        area_num_
    };

    struct block_geometry_t //Deprecated!! introduced to manage the AD ACQ non contiguos memory. No loger required since FW remove the holes
    {   //total blocks = super_block_num*block_num
        //block[n] = (n%block_num)*block_size+(n/block_size)*super_block_size
        unsigned int block_num;
        unsigned int block_size;
        unsigned int block_stride;
        unsigned int super_block_num;
        unsigned int super_block_stride;
    };

    struct destination_t
    {
        unsigned long address;
        unsigned int event;

        bool evenValid() const { return event!=evet_invalid;}
        unsigned int eventCode() const { return event;}
        unsigned long targetAddress() const { return address;}
    };

    typedef unsigned int destination_id_t;

    const char* name;

    unsigned int max_size_bytes;

    destination_id_t dstId;

    destination_t dst[area_num_];


    bool read_back_enable;  //Can be read-back for testing
    bool not_writable;

    void* default_memory;

    block_geometry_t geometry;

    function_driver_default_memory_initializer_t function_driver_default_memory_initializer;

public:
    //Some helper methods:
    destination_id_t destinationId() const { return dstId;}
    unsigned int size() const { return max_size_bytes;}
    const destination_t& destination(area_t a) const { return dst[a];}

    bool isReadble() const { return read_back_enable;}

    bool isWritable() const { return !not_writable;}

    void* defaultMemory() const { return default_memory;}
};

class GrifoCoreFwContext
{
public:
    enum function_t {
        timer_tx,
        timer_hr,

        ctrl_link_rcv_tx,
        ctrl_link_rcv_rx,

        ctrl_link_exc_tx,
        ctrl_link_exc_rx,

        aesa_tx,
        aesa_rx,
        aesa_rx_redoundant,

        timetag,

        ad_ctrl,
        ad_capture,

        detector,
        expander,
        expander_hr,

        pulse_compressor,

        dispatcher_cfg,

        processing_header,

        scratch_,

        function_nums_
    };

    template<typename T_> static inline function_t toFid(T_ id) { return static_cast<function_t>(id);}

    static GrifoCoreFwFunction::area_t freeArea();
    static GrifoCoreFwFunction::area_t busyArea();

    static void setFreeArea(GrifoCoreFwFunction::area_t);
    static void setFreeArea(unsigned int );
    static void areaPingPong();

    static const GrifoCoreFwFunction& function(function_t);

    static void setDefaultMemory(function_t fid, void* memory);

    template<class ALLOCATOR_> static void allocateDefaultMemory(ALLOCATOR_ allocator)
    {
        for(int i=0; i<function_nums_; ++i)
        {
           function_t fid=toFid(i);
           const GrifoCoreFwFunction& f=function(fid);
           void* p=allocator(f.size());
           setDefaultMemory(fid, p);
        }

    }
};

#endif // GRIFO_CORE_FW_DRIVER_H
