/*
 * b1553_drv_mex.cpp
 *
 */


#include "mex.h"

#include "b1553_driver.h"

#include "b1553_fw_types.h"

#include <stddef.h>

#ifndef _TMS320C6X
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#endif

static unsigned long ip_ctrl_address;
static unsigned long ip_cmd_address;
static unsigned long ip_mem_address;
static unsigned int ip_remap_copy;

static const mex_cmd_param_descriptor_t map_table[] =
{
		{ "ctrl", "control area", 0, &ip_ctrl_address, &mex_mt_uint },
		{ "cmd", "cmd area", 0, &ip_cmd_address, &mex_mt_uint },
		{ "mem", "memory area", 0, &ip_mem_address, &mex_mt_uint },

		{ "c", "copy configuration", mex_cmd_qualifier, &ip_remap_copy, &mex_mt_uint},

		MEX_TABLE_END
};

static mex_res_t Cmd_Map(void);

static const mex_cmd_descriptor_t cmd_map=
{ "map", "remap ip", (mex_cmd_handler_t) Cmd_Map, map_table};

static unsigned int p_rta;
static unsigned int p_hwsw;

static const mex_cmd_param_descriptor_t rta_table[] =
{
		{ "rta", "terminal address", 0, &p_rta, &mex_mt_uint },

		{ "hw", "hard-wired", mex_cmd_qualifier, &p_hwsw, &mex_mt_uint},

		MEX_TABLE_END
};

static mex_res_t Cmd_RtaSet(void);

static const mex_cmd_descriptor_t cmd_rtaset=
{ "rtaset", "set RT address", (mex_cmd_handler_t) Cmd_RtaSet, rta_table};

static unsigned int p_imode;

static const mex_cmd_param_descriptor_t iena_table[] =
{
		{ "mode", "0=level, 1=edge", 0, &p_imode, &mex_mt_uint },

		MEX_TABLE_END
};

static mex_res_t Cmd_IEna(void)
{
	int mode=0;
	if (mex_param_is_present(&p_imode))
		mode=p_imode==0 ? 0 : 1;
	b1553_drv_enable_interrupts(mode);
	mex_msg_printf(mex_msg_info, "AVB", "Interrupt enable (mode=%d)", mode);
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_iena=
{ "iena", "enable interrupts", (mex_cmd_handler_t) Cmd_IEna, iena_table};

static mex_res_t Cmd_IDis(void)
{
	b1553_drv_disable_interrupts();
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_idis=
{ "idis", "disable interrupts", (mex_cmd_handler_t) Cmd_IDis, 0};

static mex_res_t Cmd_SetBusy()
{
	int r=-1;
	if (mex_param_is_present(&p_imode))
	{
		r=p_imode;
	}
	b1553_drv_set_status_flag(b1553_drv_busy_flag, r);
	mex_msg_printf(mex_msg_info, "AVB", "1553 Busy Flag = %d", r);
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_setbusy=
{ "setbusy", "set busy flags", (mex_cmd_handler_t) Cmd_SetBusy, iena_table};

static mex_res_t Cmd_SetTerminal()
{
	int r=-1;
	if (mex_param_is_present(&p_imode))
	{
		r=p_imode;
	}
	b1553_drv_set_status_flag(b1553_drv_terminal_flag, r);
	mex_msg_printf(mex_msg_info, "AVB", "1553 Terminal Flag = %d", r);
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_setterminal=
{ "setterminal", "set terminal flags", (mex_cmd_handler_t) Cmd_SetTerminal, iena_table};

static mex_res_t Cmd_SetBiteWord()
{
	int r=-1;
	if (mex_param_is_present(&p_imode))
	{
		r=p_imode;
	}
	b1553_drv_set_bite_word(p_imode);
	mex_msg_printf(mex_msg_info, "AVB", "1553 Byte Word = 0x%u", r);
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_setbiteword=
{ "setbiteword", "set bite word", (mex_cmd_handler_t) Cmd_SetBiteWord, iena_table};

static mex_res_t Cmd_SetSubsystem()
{
	int r=-1;
	if (mex_param_is_present(&p_imode))
	{
		r=p_imode;
	}
	b1553_drv_set_status_flag(b1553_drv_subsystem_flag, r);
	mex_msg_printf(mex_msg_info, "AVB", "1553 Subsystem Flag = %d", r);
	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_setsubsystem=
{ "setsubsystem", "set subsystem flags", (mex_cmd_handler_t) Cmd_SetSubsystem, iena_table};

static const mex_mt_object_t fw_ctrl_str_lists[]=
{
  { 0, "tdcw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, tdcw), 0, mex_mt_obj_raw_fmt},
  { 0, "ticw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, ticw), 0, mex_mt_obj_raw_fmt},
  { 0, "sbap", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, sbap), 0, mex_mt_obj_raw_fmt},
  { 0, "thp", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, thp), 0, mex_mt_obj_raw_fmt},
  { 0, "tsw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, tsw), 0, mex_mt_obj_raw_fmt},

  { 0, "imcw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, imcw), 0, mex_mt_obj_raw_fmt},
  { 0, "imw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, imw), 0, mex_mt_obj_raw_fmt},

  { 0, "vw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, vw), 0, mex_mt_obj_raw_fmt},
  { 0, "version", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, version), 0, mex_mt_obj_raw_fmt},

  { 0, "ebw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, ebw), 0, mex_mt_obj_raw_fmt},
  { 0, "iqp", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, iqp), 0, mex_mt_obj_raw_fmt},
  { 0, "iack", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, iack), 0, mex_mt_obj_raw_fmt},

  { 0, "synchw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, last_synch_word), 0, mex_mt_obj_raw_fmt},

  { 0, "ttag", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, ttag), 0, mex_mt_obj_raw_fmt},

  { 0, "reset_sw", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, reset), 0, mex_mt_obj_raw_fmt},
  { 0, "ssflag", &mex_mt_uint,(void*)offsetof(b1553_fw_ctrl_regs_t, ssflag_ctrl), 0, mex_mt_obj_raw_fmt},

  {0}
};

static const mex_mt_struct_t fw_ctrl_mt=
{{"ctrl", 0, &mex_mt_struct_methods}, fw_ctrl_str_lists};

static const mex_mt_object_t fw_buff_str_lists[]=
{
  { 0, "cw", &mex_mt_uint,(void*)offsetof(b1553_fw_buffer_t, identify), 0, mex_mt_obj_raw_fmt},
  { 0, "data", &mex_mt_uint16,(void*)offsetof(b1553_fw_buffer_t, data), 32, mex_mt_obj_raw_fmt},
  { 0, "spare", &mex_mt_uint,(void*)offsetof(b1553_fw_buffer_t, spare), 0, mex_mt_obj_raw_fmt},

  {0}
};

static const mex_mt_struct_t fw_buff_mt=
{{"buff", sizeof(b1553_fw_buffer_t), &mex_mt_struct_methods}, fw_buff_str_lists};

static const mex_mt_object_t fw_mem_str_lists[]=
{
  { 0, "iq", &mex_mt_uint,(void*)offsetof(b1553_fw_memory_t, iq), 1024*4, mex_mt_obj_raw_fmt},
  { 0, "drx", &mex_mt_uint,(void*)offsetof(b1553_fw_memory_t, descriptors[0]), 4*b1553_fw_memory_t::desc_num, mex_mt_obj_raw_fmt},
  { 0, "dtx", &mex_mt_uint,(void*)offsetof(b1553_fw_memory_t, descriptors[1]), 4*b1553_fw_memory_t::desc_num, mex_mt_obj_raw_fmt},
  { 0, "dbrc", &mex_mt_uint,(void*)offsetof(b1553_fw_memory_t, descriptors[2]), 4*b1553_fw_memory_t::desc_num, mex_mt_obj_raw_fmt},

  { 0, "brx", &MEX_MT_CAST(fw_buff_mt),(void*)offsetof(b1553_fw_memory_t, buffers[0]), b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},
  { 0, "btx", &MEX_MT_CAST(fw_buff_mt),(void*)offsetof(b1553_fw_memory_t, buffers[1]), b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},
  { 0, "bbrc", &MEX_MT_CAST(fw_buff_mt),(void*)offsetof(b1553_fw_memory_t, buffers[2]), b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},

  { 0, "brx_", &mex_mt_uint16,(void*)offsetof(b1553_fw_memory_t, buffers[0]), (sizeof(b1553_fw_buffer_t))*sizeof(uint16_t)*b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},
  { 0, "btx_", &mex_mt_uint16,(void*)offsetof(b1553_fw_memory_t, buffers[1]), (sizeof(b1553_fw_buffer_t))*sizeof(uint16_t)*b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},
  { 0, "bbrc_", &mex_mt_uint16,(void*)offsetof(b1553_fw_memory_t, buffers[2]), (sizeof(b1553_fw_buffer_t))*sizeof(uint16_t)*b1553_fw_memory_t::buff_num*2, mex_mt_obj_raw_fmt},

  { 0, "hist", &mex_mt_uint,(void*)offsetof(b1553_fw_memory_t, thistory), 1024*4, mex_mt_obj_raw_fmt},

  {0}
};

static const mex_mt_struct_t fw_mem_mt=
{{"mem", 0, &mex_mt_struct_methods}, fw_mem_str_lists};


static const mex_mt_object_t fw_cmd_str_lists[]=
{
  { 0, "start", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, start), 0, mex_mt_obj_raw_fmt},
  { 0, "stop", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, stop), 0, mex_mt_obj_raw_fmt},
  { 0, "exec_cl", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, exec_cl), 0, mex_mt_obj_raw_fmt},
  { 0, "clrexeccl", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, clear_exec_cl), 0, mex_mt_obj_raw_fmt},
  { 0, "acf", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, acf), 0, mex_mt_obj_raw_fmt},
  { 0, "bitack", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, bit_ack), 0, mex_mt_obj_raw_fmt},
  { 0, "reserv0", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, reserved), 0, mex_mt_obj_raw_fmt},
  { 0, "notused", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, not_used), 0, mex_mt_obj_raw_fmt},
  { 0, "resers1", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, reserved_), 0, mex_mt_obj_raw_fmt},
  { 0, "restt", &mex_mt_uint,(void*)offsetof(b1553_fw_cmd_regs_t, restart_timetag), 0, mex_mt_obj_raw_fmt},

  {0}
};

static const mex_mt_struct_t fw_cmd_mt=
{{"cmd", 0, &mex_mt_struct_methods}, fw_cmd_str_lists};

static /*const*/ mex_mt_object_t fw_str_lists[]=
{
  { 0, "ctrl", &MEX_MT_CAST(fw_ctrl_mt), 0, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "cmd", &MEX_MT_CAST(fw_cmd_mt), 0, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "mem", &MEX_MT_CAST(fw_mem_mt), 0, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  { 0, "fwlatch", &mex_mt_uint32, (void*)0x50080004, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "fwrta", &mex_mt_uint32, (void*)0x5008000C, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  MEX_CMD_REF("map", &cmd_map),
  MEX_CMD_REF("iena", &cmd_iena),
  MEX_CMD_REF("idis", &cmd_idis),

  MEX_CMD_REF("rtaset", &cmd_rtaset),

  MEX_CMD_REF("setbusy", &cmd_setbusy),
  MEX_CMD_REF("setsubsystem", &cmd_setsubsystem),
  MEX_CMD_REF("setterminal", &cmd_setterminal),
  MEX_CMD_REF("setbiteword", &cmd_setbiteword),

  {0}
};


static const mex_mt_struct_t fw_ip_mt=
{{"avb", 0, &mex_mt_struct_methods}, fw_str_lists};

extern volatile b1553_fw_ctrl_regs_t* b1553_drv_ip_ctrl_regs_;
extern volatile b1553_fw_memory_t* b1553_drv_ip_memory_;
extern volatile b1553_fw_cmd_regs_t* b1553_drv_ip_cmd_regs_;

static mex_mt_object_t avb_ip_obj={
  0, "avb", &MEX_MT_CAST(fw_ip_mt), 0
};

static mex_res_t Cmd_Map(void)
{
  b1553_drv_remap(ip_ctrl_address, ip_cmd_address, ip_mem_address, mex_param_is_present(&ip_remap_copy) ? 1 : 0);

  fw_str_lists[0].offset=(void*)b1553_drv_ip_ctrl_regs_;
  fw_str_lists[1].offset=(void*)b1553_drv_ip_cmd_regs_;
  fw_str_lists[2].offset=(void*)b1553_drv_ip_memory_;


  return mex_ok;
}


static mex_res_t Cmd_RtaSet(void)
{
	if (mex_param_is_present(&p_rta))
	{
		b1553_drv_set_rt_sw_address(p_rta);
		b1553_drv_enable_sw_rt_address(1);
	}
	if (mex_param_is_present(&p_hwsw))
	{
		b1553_drv_enable_sw_rt_address(0);
	}

	unsigned int sw_adr=0;
	unsigned int hw_adr=0;

	int sel=b1553_drv_get_rta(&sw_adr, &hw_adr);
	mex_printf("Selection=%d\n", sel);
	mex_printf("  HW=%u:%u\n", hw_adr>>1, hw_adr & 0x01);
	mex_printf("  SW=%u:%u\n", sw_adr>>1, sw_adr & 0x01);

	return mex_ok;
}

void b1553_drv_mex_initialize()
{
	fw_str_lists[0].offset=(void*)b1553_drv_ip_ctrl_regs_;
	fw_str_lists[1].offset=(void*)b1553_drv_ip_cmd_regs_;
	fw_str_lists[2].offset=(void*)b1553_drv_ip_memory_;

    mex_object_register(mex_object_root(), &avb_ip_obj);
}





