📄 circuit.cpp
字号:
//-----------------------------------------------------------------------------
// Free the entire program.
//-----------------------------------------------------------------------------
void FreeEntireProgram(void)
{
ForgetEverything();
int i;
for(i = 0; i < Prog.numRungs; i++) {
FreeCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i]);
}
Prog.numRungs = 0;
Prog.cycleTime = 10000;
Prog.mcuClock = 4000000;
Prog.baudRate = 2400;
Prog.io.count = 0;
Prog.mcu = NULL;
}
//-----------------------------------------------------------------------------
// Returns true if the given subcircuit contains the given leaf.
//-----------------------------------------------------------------------------
static BOOL ContainsElem(int which, void *any, ElemLeaf *seek)
{
switch(which) {
case ELEM_SERIES_SUBCKT: {
ElemSubcktSeries *s = (ElemSubcktSeries *)any;
int i;
for(i = 0; i < s->count; i++) {
if(ContainsElem(s->contents[i].which, s->contents[i].d.any,
seek))
{
return TRUE;
}
}
break;
}
case ELEM_PARALLEL_SUBCKT: {
ElemSubcktParallel *p = (ElemSubcktParallel *)any;
int i;
for(i = 0; i < p->count; i++) {
if(ContainsElem(p->contents[i].which, p->contents[i].d.any,
seek))
{
return TRUE;
}
}
break;
}
CASE_LEAF
if(any == seek)
return TRUE;
break;
default:
oops();
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Use ContainsElem to find the rung containing the cursor.
//-----------------------------------------------------------------------------
int RungContainingSelected(void)
{
int i;
for(i = 0; i < Prog.numRungs; i++) {
if(ContainsElem(ELEM_SERIES_SUBCKT, Prog.rungs[i], Selected)) {
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Delete the rung that contains the cursor.
//-----------------------------------------------------------------------------
void DeleteSelectedRung(void)
{
if(Prog.numRungs == 1) {
Error(_("Cannot delete rung; program must have at least one rung."));
return;
}
int gx, gy;
BOOL foundCursor;
foundCursor = FindSelected(&gx, &gy);
int i = RungContainingSelected();
if(i < 0) return;
FreeCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i]);
Prog.numRungs--;
memmove(&Prog.rungs[i], &Prog.rungs[i+1],
(Prog.numRungs - i)*sizeof(Prog.rungs[0]));
if(foundCursor) MoveCursorNear(gx, gy);
WhatCanWeDoFromCursorAndTopology();
}
//-----------------------------------------------------------------------------
// Allocate a new `empty' rung, with only a single relay coil at the end. All
// the UI code assumes that rungs always have a coil in them, so it would
// add a lot of nasty special cases to create rungs totally empty.
//-----------------------------------------------------------------------------
static ElemSubcktSeries *AllocEmptyRung(void)
{
ElemSubcktSeries *s = AllocSubcktSeries();
s->count = 1;
s->contents[0].which = ELEM_PLACEHOLDER;
ElemLeaf *l = AllocLeaf();
s->contents[0].d.leaf = l;
return s;
}
//-----------------------------------------------------------------------------
// Insert a rung either before or after the rung that contains the cursor.
//-----------------------------------------------------------------------------
void InsertRung(BOOL afterCursor)
{
if(Prog.numRungs >= (MAX_RUNGS - 1)) {
Error(_("Too many rungs!"));
return;
}
int i = RungContainingSelected();
if(i < 0) return;
if(afterCursor) i++;
memmove(&Prog.rungs[i+1], &Prog.rungs[i],
(Prog.numRungs - i)*sizeof(Prog.rungs[0]));
Prog.rungs[i] = AllocEmptyRung();
(Prog.numRungs)++;
WhatCanWeDoFromCursorAndTopology();
}
//-----------------------------------------------------------------------------
// Swap the row containing the selected element with the one under it, or do
// nothing if the rung is the last in the program.
//-----------------------------------------------------------------------------
void PushRungDown(void)
{
int i = RungContainingSelected();
if(i == (Prog.numRungs-1)) return;
ElemSubcktSeries *temp = Prog.rungs[i];
Prog.rungs[i] = Prog.rungs[i+1];
Prog.rungs[i+1] = temp;
WhatCanWeDoFromCursorAndTopology();
ScrollSelectedIntoViewAfterNextPaint = TRUE;
}
//-----------------------------------------------------------------------------
// Swap the row containing the selected element with the one above it, or do
// nothing if the rung is the last in the program.
//-----------------------------------------------------------------------------
void PushRungUp(void)
{
int i = RungContainingSelected();
if(i == 0) return;
ElemSubcktSeries *temp = Prog.rungs[i];
Prog.rungs[i] = Prog.rungs[i-1];
Prog.rungs[i-1] = temp;
WhatCanWeDoFromCursorAndTopology();
ScrollSelectedIntoViewAfterNextPaint = TRUE;
}
//-----------------------------------------------------------------------------
// Start a new project. Give them one rung, with a coil (that they can
// never delete) and nothing else.
//-----------------------------------------------------------------------------
void NewProgram(void)
{
UndoFlush();
FreeEntireProgram();
Prog.numRungs = 1;
Prog.rungs[0] = AllocEmptyRung();
}
//-----------------------------------------------------------------------------
// Worker for ItemIsLastInCircuit. Basically we look for seek in the given
// circuit, trying to see whether it occupies the last position in a series
// subcircuit (which may be in a parallel subcircuit that is in the last
// position of a series subcircuit that may be in a parallel subcircuit that
// etc.)
//-----------------------------------------------------------------------------
static void LastInCircuit(int which, void *any, ElemLeaf *seek,
BOOL *found, BOOL *andItemAfter)
{
switch(which) {
case ELEM_PARALLEL_SUBCKT: {
ElemSubcktParallel *p = (ElemSubcktParallel *)any;
int i;
for(i = 0; i < p->count; i++) {
LastInCircuit(p->contents[i].which, p->contents[i].d.any, seek,
found, andItemAfter);
if(*found) return;
}
break;
}
case ELEM_SERIES_SUBCKT: {
ElemSubcktSeries *s = (ElemSubcktSeries *)any;
LastInCircuit(s->contents[s->count-1].which,
s->contents[s->count-1].d.any, seek, found, andItemAfter);
break;
}
default:
if(*found) *andItemAfter = TRUE;
if(any == seek) *found = TRUE;
break;
}
}
//-----------------------------------------------------------------------------
// Is an item the last one in the circuit (i.e. does one of its terminals go
// to the rightmost bus bar)? We need to know this because that is the only
// circumstance in which it is okay to insert a coil, RES, etc. after
// something
//-----------------------------------------------------------------------------
BOOL ItemIsLastInCircuit(ElemLeaf *item)
{
int i = RungContainingSelected();
if(i < 0) return FALSE;
BOOL found = FALSE;
BOOL andItemAfter = FALSE;
LastInCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i], item, &found,
&andItemAfter);
if(found) return !andItemAfter;
return FALSE;
}
//-----------------------------------------------------------------------------
// Returns TRUE if the subcircuit contains any of the given instruction
// types (ELEM_....), else FALSE.
//-----------------------------------------------------------------------------
static BOOL ContainsWhich(int which, void *any, int seek1, int seek2, int seek3)
{
switch(which) {
case ELEM_PARALLEL_SUBCKT: {
ElemSubcktParallel *p = (ElemSubcktParallel *)any;
int i;
for(i = 0; i < p->count; i++) {
if(ContainsWhich(p->contents[i].which, p->contents[i].d.any,
seek1, seek2, seek3))
{
return TRUE;
}
}
break;
}
case ELEM_SERIES_SUBCKT: {
ElemSubcktSeries *s = (ElemSubcktSeries *)any;
int i;
for(i = 0; i < s->count; i++) {
if(ContainsWhich(s->contents[i].which, s->contents[i].d.any,
seek1, seek2, seek3))
{
return TRUE;
}
}
break;
}
default:
if(which == seek1 || which == seek2 || which == seek3) {
return TRUE;
}
break;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Are either of the UART functions (send or recv) used? Need to know this
// to know whether we must receive their pins.
//-----------------------------------------------------------------------------
BOOL UartFunctionUsed(void)
{
int i;
for(i = 0; i < Prog.numRungs; i++) {
if(ContainsWhich(ELEM_SERIES_SUBCKT, Prog.rungs[i],
ELEM_UART_RECV, ELEM_UART_SEND, ELEM_FORMATTED_STRING))
{
return TRUE;
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Is the PWM function used? Need to know this to know whether we must reserve
// the pin.
//-----------------------------------------------------------------------------
BOOL PwmFunctionUsed(void)
{
int i;
for(i = 0; i < Prog.numRungs; i++) {
if(ContainsWhich(ELEM_SERIES_SUBCKT, Prog.rungs[i], ELEM_SET_PWM,
-1, -1))
{
return TRUE;
}
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -