Creating DLL-Based Simulation Models in Proteus

1. Introduction to Proteus VSM Simulation Models

During the use of Proteus to simulate microcontroller systems, it is often difficult to find the required components, necessitating custom development. A key feature of Proteus VSM is its extensibility through DLL-based component models. These models are divided into two categories: Electrical Models and Graphical Models. The Electrical Model implements the electrical characteristics of components, receiving and outputting data according to specified timing; the Graphical Model facilitates user interaction during simulation, such as displaying on an LCD. A component can implement only the Electrical Model, or both the Electrical and Graphical Models.

Proteus provides several C++ abstract class interfaces for VSM models, which users need to implement in the DLL when creating components. The communication principle between the VSM model and the Proteus system is illustrated in the figure below:

Creating DLL-Based Simulation Models in Proteus

Graphical Model Interface Abstract Classes:

ICOMPONENT – An active component object within ISIS, providing drawing and user interaction services for the VSM model on the schematic.

IACTIVEMODEL – The VSM graphical model implemented by the user must inherit from this class and implement the corresponding drawing and keyboard/mouse event handling.

Electrical Model Interface Abstract Classes:

IINSTANCE – A PROSPICE simulation primitive model that provides access to properties, simulation nodes, and data pins for the VSM model, allowing the model to issue warnings and error messages through the simulation log.

ISPICECKT (Analog) – An analog component owned by SPICE, providing services to access, create, and delete nodes, allocate space on a sparse matrix, and allow the model to force simulation time points to occur and suspend simulation at given times.

ISPICEMODEL (Analog) – The VSM analog component implemented by the user must inherit from this class and implement the corresponding data loading and processing at completion time.

IDSIMCKT (Digital) – A digital component owned by DSIM, providing services to access variables in the digital system, create callback functions, and suspend simulation.

IDSIMMODEL (Digital) – The VSM digital component implemented by the user must inherit from this class and implement the corresponding pin state change judgment and callback event handling.

IDSIMPIN (Digital) – Pins of the digital component, providing services to detect pin states and create output transaction events.

IDBUSPIN (Digital) – The data or address bus of the digital component, providing services to detect bus states and create bus output transaction events.

IMIXEDMODEL (Mixed) – Inherits both ISPICEMODEL and IDSIMMODEL, indicating that the component has both analog and digital characteristics.

To allow Proteus to access member functions in the user model, an instance of the user model must be created. This cannot be achieved through class interfaces but must be done by exporting several C functions from the DLL, which must be implemented in the user model to construct and destruct the user model instance.

(1) Constructing and destructing graphical model instances:

IACTIVEMODEL *createactivemodel (CHAR *device, ILICENCESERVER *ils)

VOID deleteactivemodel (IACTIVEMODEL *model)

(2) Constructing and destructing analog electrical model instances:

ISPICEMODEL *createspicemodel (CHAR *device, ILICENCESERVER *ils)

VOID deletespicemodel (ISPICEMODEL *model)

(3) Constructing and destructing digital electrical model instances:

IDSIMMODEL *createdsimmodel (CHAR *device, ILICENCESERVER *ils)

VOID deletedsimmodel (IDSIMMODEL *model)

(4) Constructing and destructing mixed electrical model instances:

IMIXEDMODEL *createmixedmodel (CHAR *device, ILICENCESERVER *ils)

VOID deletemixedmodel (IDSIMMODEL *model)

2. Development Process of Proteus VSM Simulation Models

1. Draw component graphics, pins, and related symbols.

2. Create the component and set its properties.

3. Write the component in C++, implementing the electrical and graphical models, and compile to generate the DLL.

4. Build the circuit simulation test.

3. Example of VSM Model Development

Below, we will detail the development process using the TG19264A dot matrix LCD component as an example.

1. Open Proteus, select the menu View >> Snap 10th, and choose the 2D graphics box from the left drawing toolbar to draw the three shapes as shown in the figure.

Creating DLL-Based Simulation Models in Proteus

2. Select the 2D graphics line, draw two straight lines, set the width to 36th, and color to gray. Select 2D graphics circle to draw four mounting holes at the corners. Use Markers for component origin to draw the symbol origin for the three shapes (the red parts in the figure).

Creating DLL-Based Simulation Models in Proteus

3. Select Device pin, rotate it 90 degrees clockwise, and place 20 pins as shown in the figure. Set the electrical types for GND, VCC, V0, Vee, LED+ to PP-Power Pin, and for D/I, R/W, E, CS1, RET, CS2, CS3 to IP-Input, and for D0~D7 to IO-Bidirectional.

Creating DLL-Based Simulation Models in Proteus

4. Right-click to drag out the selection box to select the first symbol, choose the menu Library >> Create Symbol, name it LCD19264A_C, and confirm. Similarly, name the second and third symbols as LCD19264A_1 and LCD19264A_0 respectively. When the user calls drawsymbol (-1), it will draw LCD19264A_C; calling drawsymbol (1) will draw LCD19264A_1; calling drawsymbol (0) will draw LCD19264A_0.

Creating DLL-Based Simulation Models in Proteus

5. Right-click to drag out the selection box to select the symbol LCD19264A_C, choose the menu Library >> Create Component, set Device Properties as shown in the figure, and click Next >. Skip the package settings and click Next >. Set the component properties as shown in the figure, and click Next >. Select the datasheet (optional), and click Next >. Select the device library and click OK.

Creating DLL-Based Simulation Models in Proteus

Creating DLL-Based Simulation Models in Proteus

Creating DLL-Based Simulation Models in Proteus

6. Open VC, create a new project, select Win32 Dynamic-Link Library, name the project, and establish an empty DLL project. Copy VSM.HPP from the INCLUDE folder of the Proteus installation directory to the current project directory, create files LCD19264A.H and LCD19264A.CPP, and write the following code.

/*****************************************************************

* File: LCD19264A.H

* Description: The following features are not supported

* (1) Display switch control is not supported

* (2) Setting the starting line for display is not supported

*****************************************************************/

#include “vsm.hpp”

//LCD Constants

#define LCD_BLK_NUM 3 //lcd block number

#define LCD_BLK_LEN 64 //lcd block length

#define LCD_LINE_NUM 8 //lcd line number

#define LCD_LENGTH (LCD_BLK_LEN*LCD_BLK_NUM) //lcd length

#define LCD_WIDTH 64 //lcd width

#define BLANK_WIDTH 50 //the width of blank

#define SYM_LINEWIDTH 28 //the width of symbol line

//LCD Command Masks

#define CMD_MASK 0xc0

//LCD Commands

#define DISP_ONOFF 0x00 //Switch backlight

#define SET_STARTLINE 0xc0 //Set starting line

#define SET_XADDRESS 0x80 //Set X address

#define SET_YADDRESS 0x40 //Set Y address

//Delay Constants

#define DELAY_1s 1000000000000

#define DELAY_1ms 1000000000

#define DELAY_1us 1000000

#define DELAY_1ns 1000

#define DELAY_1ps 1

/*

LCD components have both digital electrical characteristics and drawing characteristics, so they must inherit from IACTIVEMODEL and IDSIMMODEL

*/

class LCD19264A : public IACTIVEMODEL, public IDSIMMODEL

{

public:

/* Electrical Model Member Functions */

//Digital circuits always return TRUE

INT isdigital (CHAR *pinname);

//Called when creating the model instance, for initialization

VOID setup (IINSTANCE *inst, IDSIMCKT *dsim);

//Simulation run mode control, called at the start of each frame in interactive simulation

VOID runctrl (RUNMODES mode);

//Called when the user changes the state of keys, etc., during interactive simulation

VOID actuate (REALTIME time, ACTIVESTATE newstate);

//Called at the end of each frame during interactive simulation, communicates with the graphical model by passing ACTIVEDATA data, thus calling animate() for drawing

BOOL indicate (REALTIME time, ACTIVEDATA *data);

//Called when pin states change, mainly used to handle data input and output

VOID simulate (ABSTIME time, DSIMMODES mode);

//Callback function that can be set to be called at a given time via setcallback()

VOID callback (ABSTIME time, EVENTID eventid);

/* Graphical Model Member Functions */

//Called when creating the model instance, for initialization

VOID initialize (ICOMPONENT *cpt);

//Called by PROSPICE, returns the analog electrical model

ISPICEMODEL *getspicemodel (CHAR *device);

//Called by PROSPICE, returns the digital electrical model

IDSIMMODEL *getdsimmodel (CHAR *device);

//Called when the schematic needs to be redrawn

VOID plot (ACTIVESTATE state);

//Called when the corresponding electrical model generates active events, commonly used to update graphics

VOID animate (INT element, ACTIVEDATA *newstate);

//Used to handle keyboard and mouse events

BOOL actuate (WORD key, INT x, INT y, DWORD flags);

private:

IINSTANCE *instance; //PROSPICE simulation primitive model

IDSIMCKT *ckt; //DSIM’s digital component

ICOMPONENT *component; //An active component object within ISIS

//Pin Definitions

IDSIMPIN *di; //D/I

IDSIMPIN *rw; //R/W

IDSIMPIN *en; //E

IDSIMPIN *cs1; //CS1

IDSIMPIN *cs2; //CS2

IDSIMPIN *cs3; //CS3

IDSIMPIN *d[8]; //D0~D7

IBUSPIN *databus; //D[0..7]

//LCD Parameters

BYTE x_addr; //X address (see manual)

BYTE y_addr; //Y address (see manual)

BYTE status; //Status (see manual)

BYTE cur_blk; //Current block number (total of 3 blocks, see manual)

BYTE DDRAM[LCD_BLK_NUM][LCD_BLK_LEN*LCD_WIDTH/8]; //LCD display RAM

BOOL new_flag; //New data arrival flag

//Display Parameters

BOX lcdarea; //LCD display area

float pix_width, pix_height; //Width and height of the rectangle corresponding to each pixel

};

/*****************************************************************

* File: LCD19264A.CPP

* Description: The following features are not supported

* (1) Display switch control is not supported

* (2) Setting the starting line for display is not supported

*****************************************************************/

#include

#include “LCD19264A.h”

//—————————————————————————-

//Implementation of the electrical model

//Constructing the digital electrical model instance

extern “C” IDSIMMODEL __declspec(dllexport) * createdsimmodel (CHAR *device, ILICENCESERVER *ils)

{

//Authorization

ils->authorize(0x88888888, 0x69); //Version 6.9

return new LCD19264A; //Create model instance

}

//Destructing the digital electrical model instance

extern “C” VOID __declspec(dllexport) deletedsimmodel (IDSIMMODEL *model)

{

delete (LCD19264A *)model; //Delete model instance

}

//Digital circuits always return TRUE

INT LCD19264A::isdigital (CHAR *pinname)

{

return 1;

}

//Called when creating the model instance, for initialization

VOID LCD19264A::setup (IINSTANCE *inst, IDSIMCKT *dsim)

{

instance = inst; //PROSPICE simulation primitive model

ckt = dsim; //DSIM’s digital component

//Get pins

di = instance->getdsimpin(“D/I,d/i”, true);

di->setstate(FLT); //FLOAT

rw = instance->getdsimpin(“R/W,r/w”, true);

rw->setstate(FLT);

en = instance->getdsimpin(“E,e”, true);

en->setstate(FLT);

cs1 = instance->getdsimpin(“CS1,cs1”, true);

cs1->setstate(FLT);

cs2 = instance->getdsimpin(“CS2,cs2”, true);

cs2->setstate(FLT);

cs3 = instance->getdsimpin(“CS3,cs3”, true);

cs3->setstate(FLT);

d[0] = instance->getdsimpin(“D0,d0”, true);

d[0]->setstate(FLT);

d[1] = instance->getdsimpin(“D1,d1”, true);

d[1]->setstate(FLT);

d[2] = instance->getdsimpin(“D2,d2”, true);

d[2]->setstate(FLT);

d[3] = instance->getdsimpin(“D3,d3”, true);

d[3]->setstate(FLT);

d[4] = instance->getdsimpin(“D4,d4”, true);

d[4]->setstate(FLT);

d[5] = instance->getdsimpin(“D5,d5”, true);

d[5]->setstate(FLT);

d[6] = instance->getdsimpin(“D6,d6”, true);

d[6]->setstate(FLT);

d[7] = instance->getdsimpin(“D7,d7”, true);

d[7]->setstate(FLT);

//For convenience, map D0~D7 to an 8-bit bus

databus = instance->getbuspin(“LCD_DBUS”, d, 8);

databus->settiming(100,100,100); //Set time delay

databus->setstates(SHI,SLO,FLT); //Set bus logic to [1,0, tri-state] driving state

//lcd model

x_addr = 0; //X address (see manual)

y_addr = 0; //Y address (see manual)

status = 0; //Status (see manual)

new_flag = TRUE; //New data arrival flag

}

//Simulation run mode control, called at the start of each frame in interactive simulation

VOID LCD19264A::runctrl (RUNMODES mode)

{

}

//Called when the user changes the state of keys, etc., during interactive simulation

VOID LCD19264A::actuate (REALTIME time, ACTIVESTATE newstate)

{

}

//Called at the end of each frame during interactive simulation, communicates with the graphical model by passing ACTIVEDATA data, thus calling animate() for drawing

BOOL LCD19264A::indicate (REALTIME time, ACTIVEDATA *data)

{

if(new_flag){

//New data has arrived

data->type = ADT_REAL; //call back animate() to refresh lcd

data->realval = (float)time*DSIMTICK;

}

return TRUE;

}

//Called when pin states change, mainly used to handle data input and output

VOID LCD19264A::simulate (ABSTIME time, DSIMMODES mode)

{

BYTE data;

if(en->isnegedge()){

//E’s falling edge arrives

if((rw->istate()==SLO)||(rw->istate()==WLO)){

//R/W low indicates write

//Read block selection

if((cs1->istate()==SLO)||(cs1->istate()==WLO))

cur_blk = 0;

else if((cs2->istate()==SLO)||(cs2->istate()==WLO))

cur_blk = 1;

else if((cs3->istate()==SLO)||(cs3->istate()==WLO))

cur_blk = 2;

else

return; //not select block

data = (BYTE)databus->getbusvalue(); //Read data

if((di->istate()==SHI)||(di->istate()==WHI)){

//D/I high indicates data

DDRAM[cur_blk][x_addr*LCD_BLK_LEN+y_addr] = data; //Write data

new_flag = TRUE; //New data arrival flag

y_addr = ((y_addr+1)%LCD_BLK_LEN); //y address auto increment

if(y_addr==0)

x_addr = ((x_addr+1)%LCD_LINE_NUM); //Auto line feed

}else{

//D/I low indicates command

switch(data&CMD_MASK)

{

case DISP_ONOFF:

//Switch backlight

break;

case SET_STARTLINE:

//Set starting line

break;

case SET_XADDRESS:

//Set X address

x_addr = (data&0x07); //bit2~bit0

break;

case SET_YADDRESS:

//Set Y address

y_addr = (data&0x3f); //bit5~bit0

break;

default:

break;

}

}else if(en->isposedge() && ((rw->istate()==SHI)||(rw->istate()==WHI))){

//E’s rising edge arrives, R/W high indicates read

if((di->istate()==SHI)||(di->istate()==WHI)){

//D/I high indicates data

//Read block selection

if((cs1->istate()==SLO)||(cs1->istate()==WLO))

cur_blk = 0;

else if((cs2->istate()==SLO)||(cs2->istate()==WLO))

cur_blk = 1;

else if((cs3->istate()==SLO)||(cs3->istate()==WLO))

cur_blk = 2;

else

return; //not select block

data = DDRAM[cur_blk][x_addr*LCD_BLK_LEN+y_addr]; //Read data

databus->drivebusvalue(time, data); //Output data

y_addr = ((y_addr+1)%LCD_BLK_LEN); //y address auto increment

if(y_addr==0)

x_addr = ((x_addr+1)%LCD_LINE_NUM); //Auto line feed

}else{

//D/I low indicates command

databus->drivebusvalue(time, status); //Output status

}

}

}//End of LCD19264A class

Welcome to follow (operation reference article: Send a message to the public account), click the blue text at the top “

Embedded Simulation Project

” or long press to identify the QR code to follow

Creating DLL-Based Simulation Models in Proteus

Leave a Comment