⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intcode.cpp

📁 plc软件的源代码 支持PIC ATMEGA单片机
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            Op(INT_COPY_BIT_TO_BIT, storeName, stateInOut);
            break;
        }
        case ELEM_LOOK_UP_TABLE: {
            // God this is stupid; but it will have to do, at least until I
            // add new int code instructions for this.
            int i;
            Op(INT_IF_BIT_SET, stateInOut);
            ElemLookUpTable *t = &(l->d.lookUpTable);
            for(i = 0; i < t->count; i++) {
                Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", i);
                Op(INT_IF_VARIABLE_EQUALS_VARIABLE, t->index, "$scratch");
                    Op(INT_SET_VARIABLE_TO_LITERAL, t->dest, t->vals[i]);
                Op(INT_END_IF);
            }
            Op(INT_END_IF);
            break;
        }
        case ELEM_PIECEWISE_LINEAR: {
            // This one is not so obvious; we have to decide how best to
            // perform the linear interpolation, using our 16-bit fixed
            // point math.
            ElemPiecewiseLinear *t = &(l->d.piecewiseLinear);
            if(t->count == 0) {
                Error(_("Piecewise linear lookup table with zero elements!"));
                CompileError();
            }
            int i;
            int xThis = t->vals[0];
            for(i = 1; i < t->count; i++) {
                if(t->vals[i*2] <= xThis) {
                    Error(_("x values in piecewise linear table must be "
                        "strictly increasing."));
                    CompileError();
                }
                xThis = t->vals[i*2];
            }
            Op(INT_IF_BIT_SET, stateInOut);
            for(i = t->count - 1; i >= 1; i--) {
                Op(INT_IF_VARIABLE_LES_LITERAL, t->index, t->vals[i*2]+1);
                int thisDx = t->vals[i*2] - t->vals[(i-1)*2];
                int thisDy = t->vals[i*2 + 1] - t->vals[(i-1)*2 + 1];
                // The output point is given by
                //    yout = y[i-1] + (xin - x[i-1])*dy/dx
                // and this is the best form in which to keep it, numerically
                // speaking, because you can always fix numerical problems
                // by moving the PWL points closer together.
               
                // Check for numerical problems, and fail if we have them.
                if((thisDx*thisDy) >= 32767 || (thisDx*thisDy) <= -32768) {
                    Error(_("Numerical problem with piecewise linear lookup "
                        "table. Either make the table entries smaller, "
                        "or space the points together more closely.\r\n\r\n"
                        "See the help file for details."));
                    CompileError();
                }

                Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", t->vals[(i-1)*2]);
                Op(INT_SET_VARIABLE_SUBTRACT, "$scratch", t->index,
                    "$scratch", 0);
                Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch2", thisDx);
                Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch3", thisDy);
                Op(INT_SET_VARIABLE_MULTIPLY, t->dest, "$scratch", "$scratch3",
                    0);
                Op(INT_SET_VARIABLE_DIVIDE, t->dest, t->dest, "$scratch2", 0);

                Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch",
                    t->vals[(i-1)*2 + 1]);
                Op(INT_SET_VARIABLE_ADD, t->dest, t->dest, "$scratch", 0);
                Op(INT_END_IF);
            }
            Op(INT_END_IF);
            break;
        }
        case ELEM_FORMATTED_STRING: {
            // Okay, this one is terrible and ineffcient, and it's a huge pain
            // to implement, but people want it a lot. The hard part is that
            // we have to let the PLC keep cycling, of course, and also that
            // we must do the integer to ASCII conversion sensisbly, with
            // only one divide per PLC cycle.

            // This variable is basically our sequencer: it is a counter that
            // increments every time we send a character.
            char seq[MAX_NAME_LEN];
            GenSymFormattedString(seq);

            // The variable whose value we might interpolate.
            char *var = l->d.fmtdStr.var;

            // This is the state variable for our integer-to-string conversion.
            // It contains the absolute value of var, possibly with some
            // of the higher powers of ten missing.
            char convertState[MAX_NAME_LEN];
            GenSymFormattedString(convertState);

            // We might need to suppress some leading zeros.
            char isLeadingZero[MAX_NAME_LEN];
            GenSymFormattedString(isLeadingZero);

            // This is a table of characters to transmit, as a function of the
            // sequencer position (though we might have a hole in the middle
            // for the variable output)
            char outputChars[MAX_LOOK_UP_TABLE_LEN];

            BOOL mustDoMinus = FALSE;

            // The total number of characters that we transmit, including
            // those from the interpolated variable.
            int steps;

            // The total number of digits to convert.
            int digits = -1;

            // So count that now, and build up our table of fixed things to
            // send.
            steps = 0;
            char *p = l->d.fmtdStr.string;
            while(*p) {
                if(*p == '\\' && (isdigit(p[1]) || p[1] == '-')) {
                    if(digits >= 0) {
                        Error(_("Multiple escapes (\\0-9) present in format "
                            "string, not allowed."));
                        CompileError();
                    }
                    p++;
                    if(*p == '-') {
                        mustDoMinus = TRUE;
                        outputChars[steps++] = 1;
                        p++;
                    }
                    if(!isdigit(*p) || (*p - '0') > 5 || *p == '0') {
                        Error(_("Bad escape sequence following \\; for a "
                            "literal backslash, use \\\\"));
                        CompileError();
                    }
                    digits = (*p - '0');
                    int i;
                    for(i = 0; i < digits; i++) {
                        outputChars[steps++] = 0;
                    }
                } else if(*p == '\\') {
                    p++;
                    switch(*p) {
                        case 'r': outputChars[steps++] = '\r'; break;
                        case 'n': outputChars[steps++] = '\n'; break;
                        case 'b': outputChars[steps++] = '\b'; break;
                        case 'f': outputChars[steps++] = '\f'; break;
                        case '\\': outputChars[steps++] = '\\'; break;
                        case 'x': {
                            int h, l;
                            p++;
                            h = HexDigit(*p);
                            if(h >= 0) {
                                p++;
                                l = HexDigit(*p);
                                if(l >= 0) {
                                    outputChars[steps++] = (h << 4) | l;
                                    break;
                                }
                            }
                            Error(_("Bad escape: correct form is \\xAB."));
                            CompileError();
                            break;
                        }
                        default:
                            Error(_("Bad escape '\\%c'"), *p);
                            CompileError();
                            break;
                    }
                } else {
                    outputChars[steps++] = *p;
                }
                if(*p) p++;
            }

            if(digits >= 0 && (strlen(var) == 0)) {
                Error(_("Variable is interpolated into formatted string, but "
                    "none is specified."));
                CompileError();
            } else if(digits < 0 && (strlen(var) > 0)) {
                Error(_("No variable is interpolated into formatted string, "
                    "but a variable name is specified. Include a string like "
                    "'\\-3', or leave variable name blank."));
                CompileError();
            }

            // We want to respond to rising edges, so yes we need a one shot.
            char oneShot[MAX_NAME_LEN];
            GenSymOneShot(oneShot);

            Op(INT_IF_BIT_SET, stateInOut);
                Op(INT_IF_BIT_CLEAR, oneShot);
                    Op(INT_SET_VARIABLE_TO_LITERAL, seq, (SWORD)0);
                Op(INT_END_IF);
            Op(INT_END_IF);
            Op(INT_COPY_BIT_TO_BIT, oneShot, stateInOut);

            // Everything that involves seqScratch is a terrible hack to
            // avoid an if statement with a big body, which is the risk
            // factor for blowing up on PIC16 page boundaries.

            char *seqScratch = "$scratch3";

            Op(INT_SET_VARIABLE_TO_VARIABLE, seqScratch, seq);

            // No point doing any math unless we'll get to transmit this
            // cycle, so check that first.

            Op(INT_IF_VARIABLE_LES_LITERAL, seq, steps);
            Op(INT_ELSE);
                Op(INT_SET_VARIABLE_TO_LITERAL, seqScratch, -1);
            Op(INT_END_IF);

            Op(INT_CLEAR_BIT, "$scratch");
            Op(INT_UART_SEND, "$scratch", "$scratch");
            Op(INT_IF_BIT_SET, "$scratch");
                Op(INT_SET_VARIABLE_TO_LITERAL, seqScratch, -1);
            Op(INT_END_IF);

            // So we transmit this cycle, so check out which character.
            int i;
            int digit = 0;
            for(i = 0; i < steps; i++) {
                if(outputChars[i] == 0) {
                    // Note gross hack to work around limit of range for
                    // AVR brne op, which is +/- 64 instructions.
                    Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", i);
                    Op(INT_CLEAR_BIT, "$scratch");
                    Op(INT_IF_VARIABLE_EQUALS_VARIABLE, "$scratch", seqScratch);
                        Op(INT_SET_BIT, "$scratch");
                    Op(INT_END_IF);

                    Op(INT_IF_BIT_SET, "$scratch");

                    // Start the integer-to-string

                    // If there's no minus, then we have to load up
                    // convertState ourselves the first time.
                    if(digit == 0 && !mustDoMinus) {
                        Op(INT_SET_VARIABLE_TO_VARIABLE, convertState, var);
                    }
                    if(digit == 0) {
                        Op(INT_SET_BIT, isLeadingZero);
                    }
                    
                    Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch",
                        TenToThe((digits-digit)-1));
                    Op(INT_SET_VARIABLE_DIVIDE, "$scratch2", convertState,
                        "$scratch", 0);
                    Op(INT_SET_VARIABLE_MULTIPLY, "$scratch", "$scratch",
                        "$scratch2", 0);
                    Op(INT_SET_VARIABLE_SUBTRACT, convertState,
                        convertState, "$scratch", 0);
                    Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", '0');
                    Op(INT_SET_VARIABLE_ADD, "$scratch2", "$scratch2",
                        "$scratch", 0);

                    // Suppress all but the last leading zero.
                    if(digit != (digits - 1)) {
                        Op(INT_IF_VARIABLE_EQUALS_VARIABLE, "$scratch",
                            "$scratch2");
                            Op(INT_IF_BIT_SET, isLeadingZero);
                                Op(INT_SET_VARIABLE_TO_LITERAL,
                                    "$scratch2", ' ');
                            Op(INT_END_IF);
                        Op(INT_ELSE);
                            Op(INT_CLEAR_BIT, isLeadingZero);
                        Op(INT_END_IF);
                    }

                    Op(INT_END_IF);

                    digit++;
                } else if(outputChars[i] == 1) {
                    // do the minus; ugliness to get around the BRNE jump
                    // size limit, though
                    Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", i);
                    Op(INT_CLEAR_BIT, "$scratch");
                    Op(INT_IF_VARIABLE_EQUALS_VARIABLE, "$scratch", seqScratch);
                        Op(INT_SET_BIT, "$scratch");
                    Op(INT_END_IF);
                    Op(INT_IF_BIT_SET, "$scratch");
                       
                        // Also do the `absolute value' calculation while
                        // we're at it.
                        Op(INT_SET_VARIABLE_TO_VARIABLE, convertState, var);
                        Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch2", ' ');
                        Op(INT_IF_VARIABLE_LES_LITERAL, var, (SWORD)0);
                            Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch2", '-');
                            Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch",
                                (SWORD)0);
                            Op(INT_SET_VARIABLE_SUBTRACT, convertState,
                                "$scratch", var, 0);
                        Op(INT_END_IF);

                    Op(INT_END_IF);
                } else {
                    // just another character
                    Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch", i);
                    Op(INT_IF_VARIABLE_EQUALS_VARIABLE, "$scratch", seqScratch);
                        Op(INT_SET_VARIABLE_TO_LITERAL, "$scratch2", 
                            outputChars[i]);
                    Op(INT_END_IF);
                }
            }

            Op(INT_IF_VARIABLE_LES_LITERAL, seqScratch, (SWORD)0);
            Op(INT_ELSE);
                Op(INT_SET_BIT, "$scratch");
                Op(INT_UART_SEND, "$scratch2", "$scratch");
                Op(INT_INCREMENT_VARIABLE, seq);
            Op(INT_END_IF);
    
            // Rung-out state: true if we're still running, else false
            Op(INT_CLEAR_BIT, stateInOut);
            Op(INT_IF_VARIABLE_LES_LITERAL, seq, steps);
                Op(INT_SET_BIT, stateInOut);
            Op(INT_END_IF);
            break;
        }
        case ELEM_OPEN:
            Op(INT_CLEAR_BIT, stateInOut);
            break;

        case ELEM_SHORT:
            // goes straight through
            break;

        case ELEM_PLACEHOLDER:
            Error(
              _("Empty row; delete it or add instructions before compiling."));
            CompileError();
            break;

        default:
            oops();
            break;
    }

    if(which != ELEM_SERIES_SUBCKT && which != ELEM_PARALLEL_SUBCKT) {
        // then it is a leaf; let the simulator know which leaf it
        // should be updating for display purposes
        SimState(&(l->poweredAfter), stateInOut);
    }
}

//-----------------------------------------------------------------------------
// Generate intermediate code for the entire program. Return TRUE if it worked,
// else FALSE.
//-----------------------------------------------------------------------------
BOOL GenerateIntermediateCode(void)
{
    GenSymCountParThis = 0;
    GenSymCountParOut = 0;
    GenSymCountOneShot = 0;
    GenSymCountFormattedString = 0;

    // The EEPROM addresses for the `Make Persistent' op are assigned at
    // int code generation time.
    EepromAddrFree = 0;
    
    IntCodeLen = 0;
    memset(IntCode, 0, sizeof(IntCode));

    if(setjmp(CompileErrorBuf) != 0) {
        return FALSE;
    }

    Op(INT_SET_BIT, "$mcr");

    int i;
    for(i = 0; i < Prog.numRungs; i++) {
        if(Prog.rungs[i]->count == 1 && 
            Prog.rungs[i]->contents[0].which == ELEM_COMMENT)
        {
            // nothing to do for this one
            continue;
        }
        Comment("");
        Comment("start rung %d", i+1);
        Op(INT_COPY_BIT_TO_BIT, "$rung_top", "$mcr");
        SimState(&(Prog.rungPowered[i]), "$rung_top");
        IntCodeFromCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i], "$rung_top");
    }

    return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -