/*
** HDL4SE: 软件Verilog综合仿真平台
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** LCOM: 轻量级组件对象模型
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
**   this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
**   this list of conditions and the following disclaimer in the documentation
**   and/or other materials provided with the distribution.
** * The name of the author may be used to endorse or promote products
**   derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
** THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* digitled.c
    202105221536: rxh, initial version
	202105241522：rxh, 增加Detector接口
*/

#include "stdlib.h" 
#include "stdio.h"
#include "string.h"
#include "object.h"
#include "dlist.h"
#include "bignumber.h"
#include "hdl4secell.h"

#include "glad/gl.h"
#include "GLFW/glfw3.h"

#define IMPLEMENT_GUID
#include "digitled.h"
#undef IMPLEMENT_GUID

#define WIDTH  800
#define HEIGHT 300

#define LEDCOUNT 10

/*
digit led & keyboard
*/
typedef struct _sDigitLed {
	OBJECT_HEADER
	INTERFACE_DECLARE(IHDL4SEUnit)
	HDL4SEUNIT_VARDECLARE
	INTERFACE_DECLARE(IHDL4SEDetector)
	HDL4SEDETECTOR_VARDECLARE
	DLIST_VARDECLARE
		
	IHDL4SEModule** parent;
	char* name;
	GLFWwindow* window;
	int width;
	int height;
	int count;
	unsigned int baseaddr;


	unsigned char ledvalue[LEDCOUNT];
	float ledcolor[LEDCOUNT][8][3];
	
	unsigned int keypressed;

	unsigned int portdata[8];

	int wRead;              /* 上周期的读信号 */
	unsigned int bReadAddr; /* 决定当前周期是否响应 */
	int wRead_cur;
	unsigned int bReadAddr_cur;
	 
	/* 
	从设备的7个输入端口 
		0.nwReset
		1.wWrite
		2.bWriteAddr
		3.bWriteData
		4.bWriteMask
		5.wRead
		6.bReadAddr
		7.bReadData
	*/
	IHDL4SEUnit** fromunit[7];
	int           fromindex[7];

}sDigitLed;

OBJECT_FUNCDECLARE(digitled, CLSID_DIGITLED);
HDL4SEUNIT_FUNCDECLARE(digitled, CLSID_DIGITLED, sDigitLed);
HDL4SEDETECTOR_FUNCDECLARE(digitled, CLSID_DIGITLED, sDigitLed);
DLIST_FUNCIMPL(digitled, CLSID_DIGITLED, sDigitLed);

OBJECT_FUNCIMPL(digitled, sDigitLed, CLSID_DIGITLED);


QUERYINTERFACE_BEGIN(digitled, CLSID_DIGITLED)
QUERYINTERFACE_ITEM(IID_HDL4SEUNIT, IHDL4SEUnit, sDigitLed)
QUERYINTERFACE_ITEM(IID_HDL4SEDETECTOR, IHDL4SEDetector, sDigitLed)
QUERYINTERFACE_ITEM(IID_DLIST, IDList, sDigitLed)
QUERYINTERFACE_END

static const char* digitledModuleInfo()
{
	return "1.0.0-20210522.1050 Digit Led";
}

static int keypressed = 0;

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
	if (action != GLFW_PRESS)
		return;
	if (key >= GLFW_KEY_F1 && key <= GLFW_KEY_F10) {
		key -= GLFW_KEY_F1;
		if (keypressed & (1 << key))
			keypressed &= ~(1 << key);
		else
			keypressed |= (1 << key);
	}
}

static int digitledCreate(const PARAMITEM* pParams, int paramcount, HOBJECT* pObject)
{
	sDigitLed* pobj;
	int i;
	pobj = (sDigitLed*)malloc(sizeof(sDigitLed));
	if (pobj == NULL)
		return -1;
	*pObject = 0;
	HDL4SEUNIT_VARINIT(pobj, CLSID_DIGITLED);
	INTERFACE_INIT(IHDL4SEUnit, pobj, digitled, hdl4se_unit);
	INTERFACE_INIT(IHDL4SEDetector, pobj, digitled, hdl4se_detector);
	DLIST_VARINIT(pobj, digitled);

	pobj->baseaddr = 0xF0000000;
	pobj->name = NULL;
	pobj->parent = NULL;
	for (i = 0; i < LEDCOUNT; i++) {
		int j;
		for (j = 0; j < 8; j++) {
			pobj->ledcolor[i][j][0] = 0.8f;
			pobj->ledcolor[i][j][1] = 0.1f;
			pobj->ledcolor[i][j][2] = 0.1f;
		}
		pobj->ledvalue[i] = i*23;
	}
	for (i = 0; i < paramcount; i++) {
		if (pParams[i].name == PARAMID_HDL4SE_UNIT_NAME) {
			if (pobj->name != NULL)
				free(pobj->name);
			pobj->name = strdup(pParams[i].pvalue);
		}
		else if (pParams[i].name == PARAMID_BASEADDR) {
			pobj->baseaddr = pParams[i].i32value;
		}
	}

	for (i = 0; i < 7; i++) {
		pobj->fromunit[i] = NULL;
	}

	if (!glfwInit())
		return -1;
	pobj->width = WIDTH;
	pobj->height = HEIGHT;
	pobj->wRead = 0;
	pobj->count = 0;
	pobj->wRead_cur = 0;
	pobj->window = glfwCreateWindow(WIDTH, HEIGHT, "DIGIT LED", NULL, NULL);
	if (!pobj->window)
	{
		glfwTerminate();
		return -2;
	}
	pobj->keypressed = 0;

	glfwSetWindowAspectRatio(pobj->window, 3, 1);
	
	glfwSetKeyCallback(pobj->window, key_callback);
	glfwMakeContextCurrent(pobj->window);
	gladLoadGL(glfwGetProcAddress);
	glfwSwapInterval(1);

	glfwGetFramebufferSize(pobj->window, &pobj->width, &pobj->height);

	/* 返回生成的对象 */
	OBJECT_RETURN_GEN(digitled, pobj, pObject, CLSID_DIGITLED);
	return EIID_OK;
}

static void digitledDestroy(HOBJECT object)
{
	sDigitLed* pobj;
	int i;
	pobj = (sDigitLed*)objectThis(object);
	if (pobj->name != NULL)
		free(pobj->name);
	for (i = 0; i < 7; i++) {
		objectRelease(pobj->fromunit[i]);
	}
	glfwTerminate();
	memset(pobj, 0, sizeof(sDigitLed));
	free(pobj);
}

static int digitledValid(HOBJECT object)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	return 1;
}

static int digitled_hdl4se_unit_Connect(HOBJECT object, int index, HOBJECT from, int fromindex)
{
	sDigitLed* pobj;
	IHDL4SEUnit** unit = NULL;
	pobj = (sDigitLed*)objectThis(object);
	if (index >= 0 && index < 7) {
		if (0 == objectQueryInterface(from, IID_HDL4SEUNIT, (void**)&unit)) {
			pobj->fromunit[index] = unit;
			pobj->fromindex[index] = fromindex;
			return 0;
		}
		else {
			return -2;
		}
	}
	return -1;
}

#define isLedAddr(addr) ((addr & 0xFFFFFFE0) == (pobj->baseaddr & 0xFFFFFFE0))

static int digitled_hdl4se_unit_GetValue(HOBJECT object, int index, int width, IBigNumber** value)
{
	int i;
	int sel;
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	if (index != 7) /* 只响应7.ReadData端口 */
		return -1;
	if (pobj->wRead == 0)
		return -2; /* 上周期没有读命令，不响应，高阻状态 */
	if (pobj->bReadAddr == 0) {
		/* 偏移地址为0,读按键状态 */
		objectCall1(value, AssignInt32, pobj->keypressed);
		pobj->portdata[7] = pobj->keypressed;
		return 0;
	}
	return -2;
}

static int digitled_hdl4se_unit_ClkTick(HOBJECT object)
{
	int i, j;
	int reset;
	sDigitLed* pobj;
	IBigNumber** temp = bigintegerCreate(32);
	pobj = (sDigitLed*)objectThis(object);
	pobj->keypressed = keypressed;

	for (i = 0; i < 7; i++) {
		if (0 == objectCall3(pobj->fromunit[i], GetValue, i, 32, temp)) {
			objectCall1(temp, GetInt32, &pobj->portdata[i]);
		}
	}
	objectRelease(temp);
	
	/* 读nwReset信号，看是否复位 */
	reset = pobj->portdata[0] & 1;
	if (reset == 0) {
		for (i = 0; i < LEDCOUNT; i++) {
			pobj->ledvalue[i] = 0;
		}
		pobj->keypressed = 0;
	}
	

	/* 读写命令，看是否写LED状态 */
	if (reset != 0) {
		int wWrite = 0;
		unsigned int bWriteAddr = 0xFFFFFFFF;
		int wRead = 0;
		unsigned int bReadAddr = 0xFFFFFFFF;
		wWrite = pobj->portdata[1] & 1;
		bWriteAddr = pobj->portdata[2];
		if (wWrite && isLedAddr(bWriteAddr)) {
			bWriteAddr &= 0x1f;
			if (bWriteAddr >= 0x10 && bWriteAddr <= 0x18) {
				unsigned int bWriteData;
				bWriteData = pobj->portdata[3];
				if (bWriteAddr == 0x10) {
					pobj->ledvalue[0] = bWriteData & 0xFF;
					pobj->ledvalue[1] = (bWriteData >> 8) & 0xFF;
					pobj->ledvalue[2] = (bWriteData >> 16) & 0xFF;
					pobj->ledvalue[3] = (bWriteData >> 24) & 0xFF;
				} 
				else if (bWriteAddr == 0x14) {
					pobj->ledvalue[4] = bWriteData & 0xFF;
					pobj->ledvalue[5] = (bWriteData >> 8) & 0xFF;
					pobj->ledvalue[6] = (bWriteData >> 16) & 0xFF;
					pobj->ledvalue[7] = (bWriteData >> 24) & 0xFF;
				}
				else if (bWriteAddr == 0x18) {
					pobj->ledvalue[8] = bWriteData & 0xFF;
					pobj->ledvalue[9] = (bWriteData >> 8) & 0xFF;
				}
			}
		}
		wRead = pobj->portdata[5] & 0x1;
		bReadAddr = pobj->portdata[6];
		if (wRead && isLedAddr(bReadAddr)) {
			bReadAddr &= 0x1f;
			if (bReadAddr == 0x0) {
				pobj->wRead_cur = 1;
				pobj->bReadAddr_cur = 0;
			}
		}
	}

	for (i = 0; i < LEDCOUNT; i++) {
		for (j = 0; j < 8; j++) {
			if (pobj->ledvalue[i] & (1 << j)) {
				pobj->ledcolor[i][j][0] = 1.0f;
				pobj->ledcolor[i][j][1] = 0.1f; 
				pobj->ledcolor[i][j][2] = 0.1f;
			}
			else {
				pobj->ledcolor[i][j][0] *= 0.95f;
				pobj->ledcolor[i][j][1] *= 0.95f;
				pobj->ledcolor[i][j][2] *= 0.95f;
				if (pobj->ledcolor[i][j][0] < 0.2f)
					pobj->ledcolor[i][j][0] = 0.2f;
			}
		}
	}

	return 0;
}

#define LEDWIDTH  0.11f
#define LEDHEIGHT 0.80f
#define LEDGAPX    0.01f
#define LEDTHINX   0.015f
#define LEDANGLEX  0.02f

#define LEDGAPY    0.02f
#define LEDTHINY   0.04f
#define LEDANGLEY  0.06f

#define LEDOFFS    0.00f

static int digitled_DrawDigit(sDigitLed* pobj, int ind)
{
	float xoffs = -0.9f + (9-ind) * (LEDWIDTH + LEDTHINX * 5);
	float yoffs = -LEDHEIGHT / 2.0f + 0.2f;

	/* seg a */
	glColor3f(pobj->ledcolor[ind][0][0], pobj->ledcolor[ind][0][1], pobj->ledcolor[ind][0][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS + LEDGAPX,				yoffs + LEDHEIGHT);
	glVertex2f(xoffs + LEDOFFS + LEDANGLEX,			yoffs + LEDHEIGHT + LEDTHINY);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH - LEDANGLEX, yoffs + LEDHEIGHT + LEDTHINY);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH - LEDGAPX,	yoffs + LEDHEIGHT);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH - LEDANGLEX, yoffs + LEDHEIGHT - LEDTHINY);
	glVertex2f(xoffs + LEDOFFS + LEDANGLEX,			yoffs + LEDHEIGHT - LEDTHINY);
	glEnd();

	/* seg b */
	glColor3f(pobj->ledcolor[ind][1][0], pobj->ledcolor[ind][1][1], pobj->ledcolor[ind][1][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH,			yoffs + LEDHEIGHT - LEDGAPY);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH + LEDTHINX, yoffs + LEDHEIGHT - LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH + LEDTHINX, yoffs + LEDHEIGHT / 2.0f + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH,			yoffs + LEDHEIGHT / 2.0f + LEDGAPY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH - LEDTHINX, yoffs + LEDHEIGHT / 2.0f + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS + LEDWIDTH - LEDTHINX, yoffs + LEDHEIGHT - LEDANGLEY);
	glEnd();

	/* seg c */
	glColor3f(pobj->ledcolor[ind][2][0], pobj->ledcolor[ind][2][1], pobj->ledcolor[ind][2][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH, yoffs + LEDHEIGHT / 2.0f - LEDGAPY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH + LEDTHINX, yoffs + LEDHEIGHT / 2.0f - LEDANGLEY);
	glVertex2f(xoffs + LEDWIDTH + LEDTHINX, yoffs + LEDANGLEY);
	glVertex2f(xoffs + LEDWIDTH, yoffs  + LEDGAPY);
	glVertex2f(xoffs + LEDWIDTH - LEDTHINX, yoffs + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH - LEDTHINX, yoffs + LEDHEIGHT / 2.0f - LEDANGLEY);
	glEnd();

	/* seg d */
	glColor3f(pobj->ledcolor[ind][3][0], pobj->ledcolor[ind][3][1], pobj->ledcolor[ind][3][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDGAPX, yoffs);
	glVertex2f(xoffs + LEDANGLEX, yoffs + LEDTHINY);
	glVertex2f(xoffs + LEDWIDTH - LEDANGLEX, yoffs + LEDTHINY);
	glVertex2f(xoffs + LEDWIDTH - LEDGAPX, yoffs);
	glVertex2f(xoffs + LEDWIDTH - LEDANGLEX, yoffs - LEDTHINY);
	glVertex2f(xoffs + LEDANGLEX, yoffs - LEDTHINY);
	glEnd();

	/* seg e */
	glColor3f(pobj->ledcolor[ind][4][0], pobj->ledcolor[ind][4][1], pobj->ledcolor[ind][4][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS / 2.0f, yoffs + LEDHEIGHT / 2.0f - LEDGAPY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDTHINX, yoffs + LEDHEIGHT / 2.0f - LEDANGLEY);
	glVertex2f(xoffs + LEDTHINX, yoffs + LEDANGLEY);
	glVertex2f(xoffs, yoffs + LEDGAPY);
	glVertex2f(xoffs - LEDTHINX, yoffs + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f - LEDTHINX, yoffs + LEDHEIGHT / 2.0f - LEDANGLEY);
	glEnd();

	/* seg f */
	glColor3f(pobj->ledcolor[ind][5][0], pobj->ledcolor[ind][5][1], pobj->ledcolor[ind][5][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS, yoffs + LEDHEIGHT - LEDGAPY);
	glVertex2f(xoffs + LEDOFFS + LEDTHINX, yoffs + LEDHEIGHT - LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDTHINX, yoffs + LEDHEIGHT / 2.0f + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS / 2.0f, yoffs + LEDHEIGHT / 2.0f + LEDGAPY);
	glVertex2f(xoffs + LEDOFFS / 2.0f - LEDTHINX, yoffs + LEDHEIGHT / 2.0f + LEDANGLEY);
	glVertex2f(xoffs + LEDOFFS - LEDTHINX, yoffs + LEDHEIGHT - LEDANGLEY);
	glEnd();

	/* seg g */
	glColor3f(pobj->ledcolor[ind][6][0], pobj->ledcolor[ind][6][1], pobj->ledcolor[ind][6][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDGAPX, yoffs + LEDHEIGHT / 2.0f);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDANGLEX, yoffs + LEDHEIGHT / 2.0f + LEDTHINY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH - LEDANGLEX, yoffs + LEDHEIGHT / 2.0f + LEDTHINY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH - LEDGAPX, yoffs + LEDHEIGHT / 2.0f);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDWIDTH - LEDANGLEX, yoffs + LEDHEIGHT / 2.0f - LEDTHINY);
	glVertex2f(xoffs + LEDOFFS / 2.0f + LEDANGLEX, yoffs + LEDHEIGHT / 2.0f - LEDTHINY);
	glEnd();

	/* seg dp */
	glColor3f(pobj->ledcolor[ind][7][0], pobj->ledcolor[ind][7][1], pobj->ledcolor[ind][7][2]);
	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDWIDTH + LEDTHINX * 1.5, yoffs + 0.5 * LEDTHINY);
	glVertex2f(xoffs + LEDWIDTH + LEDTHINX * 3, yoffs - 1 * LEDTHINY);
	glVertex2f(xoffs + LEDWIDTH + LEDTHINX * 1.5, yoffs - 2.5 * LEDTHINY);
	glVertex2f(xoffs + LEDWIDTH + LEDTHINX * 0, yoffs - 1 * LEDTHINY);
	glEnd();

	/* keyboard status */
	if (pobj->keypressed & (1 << ind)) {
		glColor3f(1.0f, 0.0f, 0.0f);
	}
	else {
		glColor3f(0.0f, 1.0f, 0.0f);
	}

	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(xoffs + LEDTHINX, yoffs - LEDTHINY * 8);
	glVertex2f(xoffs + LEDTHINX, yoffs - LEDTHINY * 13);
	glVertex2f(xoffs + LEDWIDTH - LEDTHINX, yoffs - LEDTHINY * 13);
	glVertex2f(xoffs + LEDWIDTH - LEDTHINX, yoffs - LEDTHINY * 8);
	glEnd();
	return 0;
}


static int digitled_Render(sDigitLed* pobj)
{
	int i;
	glfwGetFramebufferSize(pobj->window, &pobj->width, &pobj->height);
	glViewport(0, 0, pobj->width, pobj->height);
	glClearColor(0.0f, 0.0f, 0.2f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	for (i = 0; i < LEDCOUNT; i++) {
		digitled_DrawDigit(pobj, i);
	}
	return 1;
}

int StopRunning();

static int digitled_hdl4se_unit_Setup(HOBJECT object)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	/*读信号和读地址寄存一拍*/
	pobj->wRead = pobj->wRead_cur;
	pobj->bReadAddr = pobj->bReadAddr_cur;
	pobj->count++;
	/* 每256个周期新绘制一次 */
	if ((pobj->count & 0xff) == 0) {
		if (digitled_Render(pobj)) {
			/* Swap buffers */
			glfwSwapBuffers(pobj->window);
		}
	}

	glfwPollEvents();

	/* Check if we are still running */
	if (glfwWindowShouldClose(pobj->window))
		StopRunning();
	return 0;
}

static int digitled_hdl4se_detector_GetName(HOBJECT object, const char** pname)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	*pname = pobj->name;
	return 0;
}

static int digitled_hdl4se_detector_GetSignalCount(HOBJECT object)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	return 9;
}

static const char* digitled_dataname[9] = {
	"nwReset",
	"wWrite",
	"bWriteAddr",
	"bWriteData",
	"bWriteMask",
	"wRead",
	"bReadAddr",
	"bReadData",
	"BASEADDR"
};

static const char* digitled_datawidth[9] ={
	1, 1, 32, 32, 4, 1, 32, 32, 32
};

static int digitled_hdl4se_detector_GetSignalInfo(HOBJECT object, int index, const char** pname, int * width)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	if (index < 0 || index >= 9)
		return -1;
	*pname = digitled_dataname[index];
	*width = digitled_datawidth[index];
	return 0;
}

static int digitled_hdl4se_detector_GetSignalValue(HOBJECT object, int index, IBigNumber** value)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	if (index < 0 || index >= 9)
		return -1;
	objectCall2(value, SetWidth, 32, 0);
	if (index < 8)
		objectCall1(value, AssignInt32, pobj->portdata[index]);
	if (index == 8)
		objectCall1(value, AssignInt32, pobj->baseaddr);
	objectCall2(value, SetWidth, digitled_datawidth[index], 0);
	return 0;
}

static int digitled_hdl4se_detector_GetUnitCount(HOBJECT object)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	return 0;
}

static int digitled_hdl4se_detector_GetUnit(HOBJECT object, int index, HOBJECT* unit)
{
	sDigitLed* pobj;
	pobj = (sDigitLed*)objectThis(object);
	return 0;
}



IHDL4SEUnit** guiCreate(unsigned int baseaddr, const char * name)
{
	int ret;
	IHDL4SEUnit** gui;
	PARAMITEM param[2];
	IHDL4SEUnit** result = NULL;
	param[0].name = PARAMID_BASEADDR;
	param[0].i32value = baseaddr;
	param[1].name = PARAMID_HDL4SE_UNIT_NAME;
	param[1].pvalue = name;
	A_u_t_o_registor_digitled();
	ret = objectCreateEx(CLSID_DIGITLED, param, 2, IID_HDL4SEUNIT, (const void**)&gui);
	return gui;
}