对于整个CirSim软件的的架构,整体思路是将GUI和DATA分开编写,分别放在SoftGUI和ACSimulator文件夹中。
元器件建模:
- 由于电路主要由元器件,引脚,线路连接构成,各项参数也是有这三者进行传递,所以三者需要相互独立,我们首先对元器件基类eElement进行建模,先上头文件:
#ifndef EELEMENT_H
#define EELEMENT_H
#include <string>
#include <math.h>
#include <QPointer>
#include <QDebug>
#include "epin.h"
class MAINMODULE_EXPORT eElement
{
public:
/**
* @brief eElement::eElement 将当前元件添加到元件链表m_elementLis
* @param id 当前元器件名称
*/
eElement( std::string id=0 );
/**
* @brief ~eElement 类element析构函数,析构同时将当前元件从m_elementLis中删除
* 将element中的析构函数虚拟化,在继承该类的各种元器件类中重写,释放类element时释放各个子类元器件对象内存
*/
virtual ~eElement();
/**
* @brief eElement::initEpins ,默认引脚个数(2个)
*/
virtual void initEpins();
/**
* @brief eElement::setNumEpins 指定当前元件的引脚并用epin初始化
* @param n 引脚个数
*/
virtual void setNumEpins( int n );
/**
* @brief getEpin 获取引脚pin的属性
* @param pin 引脚序号
* @return
*/
virtual ePin* getEpin( int pin );
/**
* @brief getEpin 由于
* @param pinName
* @return
*/
virtual ePin* getEpin( QString pinName );
/**
* @brief setEpin 设置当前引脚属性
* @param num
* @param pin 具体引脚属性在调用ePin时实现
*/
virtual void setEpin( int num, ePin* pin );
std::string getId( ){ return m_elmId; }
virtual void initialize(){;}
virtual void resetState(){;}
virtual void stamp(){;}
virtual void simuClockStep(){;}
virtual void updateStep(){;}
/**
* @brief setVChanged 修改电压
*/
virtual void setVChanged(){;}
///
/// \brief cero_doub 默认值
///
static constexpr double cero_doub = 1e-14;
static constexpr double high_imp = 1e14;
///
/// \brief digital_high 默认高电平
///
static constexpr double digital_high = 5.0;
///
/// \brief digital_low 默认低电平
///
static constexpr double digital_low = 0.0;
static constexpr double digital_threshold = 2.5;
protected:
///
/// \brief m_ePin 元器件引脚容器
///
std::vector<ePin*> m_ePin;
///
/// \brief m_elmId 元器件名称
///
std::string m_elmId;
};
#endif
- 考虑到继承eElement的元器件成员类会在堆区申请空间,所以我们除了将主要的一些对于元器件本身属性设置的函数虚拟化(由于每个元器件的引脚以及属性不同所以在子类具体实现,当然也可以设置默认值)之外,将析构函数~eElement()也进行虚拟化,方便后续重写。
类eElement 函数的解析:
**2.1.构造函数:**由于我们还不知道后续需要添对元器件进行何种操作,此处仅将元器件传入ID进行命名即可。
**2.2 对引脚的操作:**由于每个元器件的引脚个数不一,所以我们将引脚封装成独立的对象,再元器件的引脚进行设置,声明元器件的引脚类型容器 m_ePin,用以存储当前容器的各个引脚,首先要利用函数setNumEpins()分配元器件引脚个数(由于大多数模拟电子元器件的引脚数为2,所以我们初始化引脚个数函数initEpins()设置个数为2),函数setEPin()用以设置引脚属性(按引脚序号),getEpin(int&Qstring)为后续调用对应引脚提供接口。
源文件:
#include "e-element.h"
#include <sstream>
#include <QDebug>
/**
* @brief eElement::eElement 将当前元件添加到元件链表m_elementLis
* @param id 当前元器件名称
*/
eElement::eElement( std::string id )
{
m_elmId = id;
//qDebug() << "eElement::eElement" << QString::fromStdString( m_elmId );
}
/**
* @brief eElement::~eElement 析构并将当前元件从m_elementLis中删除
*/
eElement::~eElement()
{
//qDebug() << "eElement::~eElement deleting" << QString::fromStdString( m_elmId );
/*foreach (ePin* epin, m_ePin)
{
delete epin;
}*/
m_ePin.clear();
}
/**
* @brief eElement::initEpins ,默认引脚个数(2个)
*/
void eElement::initEpins()
{
setNumEpins(2);
}
/**
* @brief eElement::setNumEpins 指定当前元件的引脚并用epin初始化
* @param n 引脚个数
*/
void eElement::setNumEpins( int n )
{
m_ePin.resize(n);
//qDebug() << "eElement::setNumEpins"<< QString::fromStdString( m_elmId )<<m_ePin.size();
for( int i=0; i<n; i++ )
{
//qDebug() << "eElement::setNumEpins PIN:"<<i<<m_ePin[i];
if( m_ePin[i] == 0 )
{
//qDebug() << "eElement::setNumEpins Creating:"<<i;
std::stringstream ss;
ss << m_elmId << "-ePin" << i; //元件m_elmId的第 i 个引脚
m_ePin[i] = new ePin( ss.str(), i ); //构造引脚
}
}
}
ePin* eElement::getEpin( int pin )
{
return m_ePin[pin];
}
ePin* eElement::getEpin( QString pinName )
{
qDebug() << "eElement::getEpin" << pinName;
if ( pinName == "lPin") return m_ePin[0];
else if( pinName == "rPin") return m_ePin[1];
else if( pinName.contains("ePin") )
{
int pin = pinName.split("-").last().remove("ePin").toInt();
return m_ePin[pin];
}
return 0l;
}
void eElement::setEpin( int num, ePin* pin )
{
m_ePin[num] = pin;
}
这样元器件模型基类就初步封装完成,后续有什么需要添加的再回来修改。