/*
 * vp_ip_mex.cpp
 *
 *  Created on: 25/set/2018
 *      Author: chessaa
 */


#include "mex.h"

#include "vg_driver.h"

#include "vg_ip_types.h"

#include <stddef.h>

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

static unsigned long ip_map_address;
static unsigned long ip_palet_address;
static unsigned long ip_fb_address;
static unsigned int ip_remap_copy;
static unsigned int ip_dac_ena;
static unsigned int ip_palet_copy;

extern unsigned int vg_ip_dbg_no_update_;
extern unsigned long vg_ip_fb_offset_;
extern unsigned int vg_ip_wdelay_;

static const mex_cmd_param_descriptor_t map_table[] =
{
		{ "adr", "address", 0, &ip_map_address, &mex_mt_uint },
		{ "pal", "gfx palet address", 0, &ip_palet_address, &mex_mt_uint },
		{ "fb", "gfx fb address", 0, &ip_fb_address, &mex_mt_uint },

		{ "c", "copy configuration", mex_cmd_qualifier, &ip_remap_copy, &mex_mt_uint},
		{ "d", "enable DAC", mex_cmd_qualifier, &ip_dac_ena, &mex_mt_uint},
		{ "p", "copy palet", mex_cmd_qualifier, &ip_palet_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 m_tp;
static unsigned int m_tp_white;

static const mex_cmd_param_descriptor_t tb_table[] =
{
		{ "pattern", "test pattern code", 0, &m_tp, &mex_mt_uint },
		{ "w", "white level", mex_cmd_qualifier|mex_cmd_required_value, &m_tp_white, &mex_mt_uint },

		MEX_TABLE_END
};

static mex_res_t Cmd_Test(void);

static const mex_cmd_descriptor_t cmd_test=
{ "testpattern", "generate test pattern", (mex_cmd_handler_t) Cmd_Test, tb_table};

static unsigned int m_vstd;

static const mex_cmd_param_descriptor_t vstd_table[] =
{
		{ "vstd", "video standard", 0, &m_vstd, &mex_mt_uint },

		MEX_TABLE_END
};

static mex_res_t Cmd_Vstd(void);

extern unsigned int vg_ip_internal_x_offset;
extern unsigned int vg_ip_interlaced;

struct vg_ip_internal_memory_t;

extern vg_ip_internal_memory_t vg_ip_internal_memory_sim_store;

static const mex_cmd_descriptor_t cmd_vstd=
{ "setstd", "set video standard", (mex_cmd_handler_t) Cmd_Vstd, vstd_table};

static /*const*/ mex_mt_object_t vg_str_lists[]=
{
  { 0, "gpal", &mex_mt_uint, 0, 256, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "spal", &mex_mt_uint, 0, 256, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  { 0, "id", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, identification), 0, mex_mt_obj_raw_fmt},
  { 0, "mode", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, mode_selector), 0, mex_mt_obj_raw_fmt},
  { 0, "vstd", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, video_standard_selector), 0, mex_mt_obj_raw_fmt},
  { 0, "cfg", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, configuration), 0, mex_mt_obj_raw_fmt},

  { 0, "gmem", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, graph_video_memory_offset), 0, mex_mt_obj_raw_fmt},
  { 0, "gwin", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, graph_window_offset), 0, mex_mt_obj_raw_fmt},

  { 0, "gmemoffset", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, vmem_offset), 0, mex_mt_obj_raw_fmt},

  { 0, "gsize", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, graph_window_size), 0, mex_mt_obj_raw_fmt},
  { 0, "gstride", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, graph_memory_stride)},

  { 0, "scmem", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, scan_video_memory_offset), 0, mex_mt_obj_raw_fmt},
  { 0, "scwin", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, scan_window_offset), 0, mex_mt_obj_raw_fmt},
  { 0, "scsize", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, scan_window_size), 0, mex_mt_obj_raw_fmt},
  { 0, "scstride", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, scan_memory_stride)},

  { 0, "bgcolor", &mex_mt_uint,(void*)offsetof(vg_ip_fw_cfg_t, default_background_color), 0, mex_mt_obj_raw_fmt},



  //{ 0, "scpal", &mex_mt_uint,(void*)offsetof(vg_ip_fw_if_t, scan_look_ip_table), 256},

  { 0, "dbg_off", &mex_mt_uint,&vg_ip_fb_offset_, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "dbg_nup", &mex_mt_uint,&vg_ip_dbg_no_update_, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  { 0, "dbg_ioff", &mex_mt_uint,&vg_ip_internal_x_offset, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},
  { 0, "dbg_iab", &mex_mt_uint,&vg_ip_interlaced, 0, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  { 0, "dbg_bram", &mex_mt_uint8,&vg_ip_internal_memory_sim_store, 512*512, mex_mt_obj_raw_fmt|mex_mt_obj_absolute},

  { 0, "dbg_delay", &mex_mt_uint8,&vg_ip_wdelay_, 0, mex_mt_obj_absolute},

  MEX_CMD_REF("map", &cmd_map),
  MEX_CMD_REF("testpattern", &cmd_test),
  MEX_CMD_REF("setstd", &cmd_vstd),

  {0}
};

static const mex_mt_struct_t vg_ip_mt=
{{"vgip", 0, &mex_mt_struct_methods}, vg_str_lists};

extern volatile vg_ip_fw_cfg_t vg_ip_fw_cfg_dummy__;	//public to be easy inspected with debugger

static mex_mt_object_t vg_ip_obj={
  0, "vg", &MEX_MT_CAST(vg_ip_mt), (void*)&vg_ip_fw_cfg_dummy__
};

static mex_res_t Cmd_Map(void)
{
  if (mex_param_is_present(&ip_map_address))
  {
	  unsigned int flags=mex_param_is_present(&ip_remap_copy) ? 1 : 0;

	  if (mex_param_is_present(&ip_dac_ena))
		  flags=flags|0x2;
	  if (mex_param_is_present(&ip_palet_copy))
		  flags=flags|0x4;

	  vg_drv_reconfigure(flags, reinterpret_cast<void*>(ip_map_address), reinterpret_cast<void*>(ip_palet_address), 0, reinterpret_cast<void*>(ip_fb_address));

	  vg_ip_obj.offset=(void*)vg_ip_cfg_;
	  vg_str_lists[0].offset=(void*)vg_ip_graph_palet_;
	  vg_str_lists[1].offset=(void*)vg_ip_sc_palet_;
  }
  mex_printf("VG IP@ 0x%8.8X, palet=0x%8.8X, fb=0x%8.8X\n", (unsigned long)vg_ip_cfg_, (unsigned long)vg_ip_graph_palet_, vg_drv_get_fr_interal_fb());

  return mex_ok;
}


static mex_res_t Cmd_Test(void)
{
	//static int pat;
	//pat=pat ^ 1;
	vg_drv_enable_test_pattern(m_tp, m_tp_white);
	return mex_ok;
}

static mex_res_t Cmd_Vstd()
{
	if (!mex_param_is_present(&m_vstd))
	{
		for(int i=0; i<20; ++i)
		{
			const vg_drv_vstd_param_t* p=vg_drv_vstd_info(i);
			if (!p)
				break;
			mex_printf("[%d] %-16.16s [%ux%u] %s\n",
					i,
					p->name,
					p->dx, p->dy,
					p->nickname);
		}
		return mex_ok;
	}

	bool left_aligned=false;
	if (m_vstd & 0x10)
	{
		m_vstd=(m_vstd & 0x0F);
		left_aligned=true;
	}

	const vg_drv_vstd_param_t* p=vg_drv_change_standard(static_cast<vg_drv_standard_t>(m_vstd), left_aligned);

    vg_ip_obj.offset=(void*)vg_ip_cfg_;
	vg_str_lists[0].offset=(void*)vg_ip_graph_palet_;
	vg_str_lists[1].offset=(void*)vg_ip_sc_palet_;

	if (p)
	{
		mex_printf("  %-16.16s [%4u x %4u] %s\n",
				p->name,
				p->dx, p->dy,
				p->nickname);
		return mex_ok;
	}

	return mex_err_invalid_range;
}

//extern vg_ip_fw_palet_t vg_ip_gfx_palet_dummy_;
//extern vg_ip_fw_palet_t vg_ip_sc_palet_dummy_;

void vg_ip_mex_initialize()
{
	 //vg_str_lists[0].offset=&vg_ip_gfx_palet_dummy_;
	 //vg_str_lists[1].offset=&vg_ip_sc_palet_dummy_;
	  vg_ip_obj.offset=(void*)vg_ip_cfg_;
	  vg_str_lists[0].offset=(void*)vg_ip_graph_palet_;
	  vg_str_lists[1].offset=(void*)vg_ip_sc_palet_;

	  mex_object_register(mex_object_root(), &vg_ip_obj);
}


