/* ** HDL4SE: 软件Verilog综合仿真平台 ** Copyright (C) 2021-2021, raoxianhong ** LCOM: 轻量级组件对象模型 ** Copyright (C) 2021-2021, raoxianhong ** 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; }