📄 intcode.cpp
字号:
stateInOut);
}
Comment("] finish series");
break;
}
case ELEM_PARALLEL_SUBCKT: {
char parThis[MAX_NAME_LEN];
GenSymParThis(parThis);
char parOut[MAX_NAME_LEN];
GenSymParOut(parOut);
Comment("start parallel [");
Op(INT_CLEAR_BIT, parOut);
ElemSubcktParallel *p = (ElemSubcktParallel *)any;
int i;
for(i = 0; i < p->count; i++) {
Op(INT_COPY_BIT_TO_BIT, parThis, stateInOut);
IntCodeFromCircuit(p->contents[i].which, p->contents[i].d.any,
parThis);
Op(INT_IF_BIT_SET, parThis);
Op(INT_SET_BIT, parOut);
Op(INT_END_IF);
}
Op(INT_COPY_BIT_TO_BIT, stateInOut, parOut);
Comment("] finish parallel");
break;
}
case ELEM_CONTACTS: {
if(l->d.contacts.negated) {
Op(INT_IF_BIT_SET, l->d.contacts.name);
} else {
Op(INT_IF_BIT_CLEAR, l->d.contacts.name);
}
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_COIL: {
if(l->d.coil.negated) {
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_CLEAR_BIT, l->d.contacts.name);
Op(INT_ELSE);
Op(INT_SET_BIT, l->d.contacts.name);
Op(INT_END_IF);
} else if(l->d.coil.setOnly) {
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_SET_BIT, l->d.contacts.name);
Op(INT_END_IF);
} else if(l->d.coil.resetOnly) {
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_CLEAR_BIT, l->d.contacts.name);
Op(INT_END_IF);
} else {
Op(INT_COPY_BIT_TO_BIT, l->d.contacts.name, stateInOut);
}
break;
}
case ELEM_RTO: {
int period = TimerPeriod(l);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.timer.name, period);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_INCREMENT_VARIABLE, l->d.timer.name);
Op(INT_END_IF);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_ELSE);
Op(INT_SET_BIT, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_RES:
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.reset.name);
Op(INT_END_IF);
break;
case ELEM_TON: {
int period = TimerPeriod(l);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.timer.name, period);
Op(INT_INCREMENT_VARIABLE, l->d.timer.name);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_END_IF);
Op(INT_ELSE);
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.timer.name);
Op(INT_END_IF);
break;
}
case ELEM_TOF: {
int period = TimerPeriod(l);
// All variables start at zero by default, so by default the
// TOF timer would start out with its output forced HIGH, until
// it finishes counting up. This does not seem to be what
// people expect, so add a special case to fix that up.
char antiGlitchName[MAX_NAME_LEN];
sprintf(antiGlitchName, "$%s_antiglitch", l->d.timer.name);
Op(INT_IF_BIT_CLEAR, antiGlitchName);
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.timer.name, period);
Op(INT_END_IF);
Op(INT_SET_BIT, antiGlitchName);
Op(INT_IF_BIT_CLEAR, stateInOut);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.timer.name, period);
Op(INT_INCREMENT_VARIABLE, l->d.timer.name);
Op(INT_SET_BIT, stateInOut);
Op(INT_END_IF);
Op(INT_ELSE);
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.timer.name);
Op(INT_END_IF);
break;
}
case ELEM_CTU: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_IF_BIT_CLEAR, storeName);
Op(INT_INCREMENT_VARIABLE, l->d.counter.name);
Op(INT_END_IF);
Op(INT_END_IF);
Op(INT_COPY_BIT_TO_BIT, storeName, stateInOut);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.counter.name,
l->d.counter.max);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_ELSE);
Op(INT_SET_BIT, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_CTD: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_IF_BIT_CLEAR, storeName);
Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", 1);
Op(INT_SET_VARIABLE_SUBTRACT, l->d.counter.name,
l->d.counter.name, "$scratch", 0);
Op(INT_END_IF);
Op(INT_END_IF);
Op(INT_COPY_BIT_TO_BIT, storeName, stateInOut);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.counter.name,
l->d.counter.max);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_ELSE);
Op(INT_SET_BIT, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_CTC: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_IF_BIT_CLEAR, storeName);
Op(INT_INCREMENT_VARIABLE, l->d.counter.name);
Op(INT_IF_VARIABLE_LES_LITERAL, l->d.counter.name,
l->d.counter.max+1);
Op(INT_ELSE);
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.counter.name,
(SWORD)0);
Op(INT_END_IF);
Op(INT_END_IF);
Op(INT_END_IF);
Op(INT_COPY_BIT_TO_BIT, storeName, stateInOut);
break;
}
case ELEM_GRT:
case ELEM_GEQ:
case ELEM_LES:
case ELEM_LEQ:
case ELEM_NEQ:
case ELEM_EQU: {
char *op1 = VarFromExpr(l->d.cmp.op1, "$scratch");
char *op2 = VarFromExpr(l->d.cmp.op2, "$scratch2");
if(which == ELEM_GRT) {
Op(INT_IF_VARIABLE_GRT_VARIABLE, op1, op2);
Op(INT_ELSE);
} else if(which == ELEM_GEQ) {
Op(INT_IF_VARIABLE_GRT_VARIABLE, op2, op1);
} else if(which == ELEM_LES) {
Op(INT_IF_VARIABLE_GRT_VARIABLE, op2, op1);
Op(INT_ELSE);
} else if(which == ELEM_LEQ) {
Op(INT_IF_VARIABLE_GRT_VARIABLE, op1, op2);
} else if(which == ELEM_EQU) {
Op(INT_IF_VARIABLE_EQUALS_VARIABLE, op1, op2);
Op(INT_ELSE);
} else if(which == ELEM_NEQ) {
Op(INT_IF_VARIABLE_EQUALS_VARIABLE, op1, op2);
} else oops();
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_ONE_SHOT_RISING: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_COPY_BIT_TO_BIT, "$scratch", stateInOut);
Op(INT_IF_BIT_SET, storeName);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_END_IF);
Op(INT_COPY_BIT_TO_BIT, storeName, "$scratch");
break;
}
case ELEM_ONE_SHOT_FALLING: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_COPY_BIT_TO_BIT, "$scratch", stateInOut);
Op(INT_IF_BIT_CLEAR, stateInOut);
Op(INT_IF_BIT_SET, storeName);
Op(INT_SET_BIT, stateInOut);
Op(INT_END_IF);
Op(INT_ELSE);
Op(INT_CLEAR_BIT, stateInOut);
Op(INT_END_IF);
Op(INT_COPY_BIT_TO_BIT, storeName, "$scratch");
break;
}
case ELEM_MOVE: {
if(IsNumber(l->d.move.dest)) {
Error(_("Move instruction: '%s' not a valid destination."),
l->d.move.dest);
CompileError();
}
Op(INT_IF_BIT_SET, stateInOut);
if(IsNumber(l->d.move.src)) {
Op(INT_SET_VARIABLE_TO_LITERAL, l->d.move.dest,
CheckMakeNumber(l->d.move.src));
} else {
Op(INT_SET_VARIABLE_TO_VARIABLE, l->d.move.dest, l->d.move.src,
0);
}
Op(INT_END_IF);
break;
}
// These four are highly processor-dependent; the int code op does
// most of the highly specific work
{
case ELEM_READ_ADC:
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_READ_ADC, l->d.readAdc.name);
Op(INT_END_IF);
break;
case ELEM_SET_PWM: {
Op(INT_IF_BIT_SET, stateInOut);
char line[80];
// ugh; need a >16 bit literal though, could be >64 kHz
sprintf(line, "%d", l->d.setPwm.targetFreq);
Op(INT_SET_PWM, l->d.readAdc.name, line);
Op(INT_END_IF);
break;
}
case ELEM_PERSIST: {
Op(INT_IF_BIT_SET, stateInOut);
// At startup, get the persistent variable from flash.
char isInit[MAX_NAME_LEN];
GenSymOneShot(isInit);
Op(INT_IF_BIT_CLEAR, isInit);
Op(INT_CLEAR_BIT, "$scratch");
Op(INT_EEPROM_BUSY_CHECK, "$scratch");
Op(INT_IF_BIT_CLEAR, "$scratch");
Op(INT_SET_BIT, isInit);
Op(INT_EEPROM_READ, l->d.persist.var, EepromAddrFree);
Op(INT_END_IF);
Op(INT_END_IF);
// While running, continuously compare the EEPROM copy of
// the variable against the RAM one; if they are different,
// write the RAM one to EEPROM.
Op(INT_CLEAR_BIT, "$scratch");
Op(INT_EEPROM_BUSY_CHECK, "$scratch");
Op(INT_IF_BIT_CLEAR, "$scratch");
Op(INT_EEPROM_READ, "$scratch", EepromAddrFree);
Op(INT_IF_VARIABLE_EQUALS_VARIABLE, "$scratch",
l->d.persist.var);
Op(INT_ELSE);
Op(INT_EEPROM_WRITE, l->d.persist.var, EepromAddrFree);
Op(INT_END_IF);
Op(INT_END_IF);
Op(INT_END_IF);
EepromAddrFree += 2;
break;
}
case ELEM_UART_SEND:
Op(INT_UART_SEND, l->d.uart.name, stateInOut);
break;
case ELEM_UART_RECV:
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_UART_RECV, l->d.uart.name, stateInOut);
Op(INT_END_IF);
break;
}
case ELEM_ADD:
case ELEM_SUB:
case ELEM_MUL:
case ELEM_DIV: {
if(IsNumber(l->d.math.dest)) {
Error(_("Math instruction: '%s' not a valid destination."),
l->d.math.dest);
CompileError();
}
Op(INT_IF_BIT_SET, stateInOut);
char *op1 = VarFromExpr(l->d.math.op1, "$scratch");
char *op2 = VarFromExpr(l->d.math.op2, "$scratch2");
int intOp;
if(which == ELEM_ADD) {
intOp = INT_SET_VARIABLE_ADD;
} else if(which == ELEM_SUB) {
intOp = INT_SET_VARIABLE_SUBTRACT;
} else if(which == ELEM_MUL) {
intOp = INT_SET_VARIABLE_MULTIPLY;
} else if(which == ELEM_DIV) {
intOp = INT_SET_VARIABLE_DIVIDE;
} else oops();
Op(intOp, l->d.math.dest, op1, op2, 0);
Op(INT_END_IF);
break;
}
case ELEM_MASTER_RELAY:
// Tricky: must set the master control relay if we reach this
// instruction while the master control relay is cleared, because
// otherwise there is no good way for it to ever become set
// again.
Op(INT_IF_BIT_CLEAR, "$mcr");
Op(INT_SET_BIT, "$mcr");
Op(INT_ELSE);
Op(INT_COPY_BIT_TO_BIT, "$mcr", stateInOut);
Op(INT_END_IF);
break;
case ELEM_SHIFT_REGISTER: {
char storeName[MAX_NAME_LEN];
GenSymOneShot(storeName);
Op(INT_IF_BIT_SET, stateInOut);
Op(INT_IF_BIT_CLEAR, storeName);
int i;
for(i = (l->d.shiftRegister.stages-2); i >= 0; i--) {
char dest[MAX_NAME_LEN+10], src[MAX_NAME_LEN+10];
sprintf(src, "%s%d", l->d.shiftRegister.name, i);
sprintf(dest, "%s%d", l->d.shiftRegister.name, i+1);
Op(INT_SET_VARIABLE_TO_VARIABLE, dest, src);
}
Op(INT_END_IF);
Op(INT_END_IF);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -