#ifndef GRIFO_CTRLINK_COMMON_H
#define GRIFO_CTRLINK_COMMON_H

#include "grifo_ctrlink.h"

#include "grifo_ctrlink_if.h"

#include "grifo_core_fw_cx.h"

#include <stdint.h>

namespace grifo_fw
{


enum function_id_t
{
    fid_status=0x10,

    fid_ad_ctrl=0x20,
    fid_ad_enable=0x21, //WARNING: always async - this functiondoes not respect the async/synch convention
    fid_test_port=0x30,
    fid_sw_dc=0x40,
    fid_lo_frq=0x50,
    fid_stc=0x60,
    fid_nagc=0x70    
};

static inline unsigned int ctrlink_address(unsigned int board, unsigned int funct, ctrlink_pingpong_t pingpong_mode)
{
    unsigned int pingpong=0;
    if (pingpong_mode<ctrlink_pingpong_auto)
        pingpong=static_cast<unsigned int>(pingpong_mode);
    else
    {
        unsigned int area=static_cast<unsigned int>(GrifoCoreFwContext::freeArea());
        pingpong=area+1;
    }
    uint32_t d=funct & 0x03FF;  //9 bits
    d|=(board & 0x0FF)<<12;
    d|=(pingpong & 0x3);
    return d;
}

template<typename T_> static inline T_* ctrlink_msg_alloc(ctrlink_blob_t* ld, unsigned int board, function_id_t fid, T_* msg=0, ctrlink_append_mode_t mode=ctrlink_append_write)
{
    unsigned int payload_size=sizeof(T_);
    uint32_t dst=ctrlink_address(board, fid, ctrlink_pingpong_auto);

    T_* m=reinterpret_cast<T_*>(ctrlink_append_raw_message(ld, dst, mode, msg, payload_size));
    return m;
}

template<typename T_> static inline T_* ctrlink_msg_alloc(ctrlink_blob_t* ld, unsigned int board, function_id_t fid, ctrlink_pingpong_t pp, T_* msg=0, ctrlink_append_mode_t mode=ctrlink_append_write)
{
    unsigned int payload_size=sizeof(T_);
    uint32_t dst=ctrlink_address(board, fid, pp);

    T_* m=reinterpret_cast<T_*>(ctrlink_append_raw_message(ld, dst, mode, msg, payload_size));
    return m;
}



extern grifo_fw::ctrlink_blob_t* ctrlink_default_blob_[ctrlink_num_instance];

static inline ctrlink_blob_t* ctrlink_validate_blob(ctrlink_blob_t* ld)
{
    return ld ? ld : ctrlink_default_blob_[0];
}

} //namespace

#endif // GRIFO_CTRLINK_COMMON_H
