Dependents:   WeatherStation

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ILinterpreter.cpp Source File

ILinterpreter.cpp

Go to the documentation of this file.
00001 /*
00002  * Instruction List interpreter library
00003  * Copyright (c) 2011 Hiroshi Suga
00004  * Released under the MIT License: http://mbed.org/license/mit
00005  */
00006 
00007 /** @file
00008  * @brief Instruction List interpreter
00009  */
00010 
00011 #include "mbed.h"
00012 #include "ILinterpreter.h"
00013 
00014 #undef DEBUG
00015 
00016 struct MNE_str {
00017     eMNEMONIC mne;
00018     char str[5];
00019 };
00020 
00021 #define IL_MNE_NUM 22
00022 static const struct MNE_str mne_str[IL_MNE_NUM] = {
00023     {MNE_DEF, "DEF"},
00024     {MNE_LD, "LD"}, {MNE_LDI, "LDI"}, {MNE_LDP, "LDP"}, {MNE_LDF, "LDF"},
00025     {MNE_OR, "OR"}, {MNE_ORI, "ORI"}, {MNE_ORP, "ORP"}, {MNE_ORF, "ORF"},
00026     {MNE_AND, "AND"}, {MNE_ANI, "ANI"}, {MNE_ANDP, "ANDP"}, {MNE_ANDF, "ANDF"},
00027     {MNE_ORB, "ORB"}, {MNE_ANB, "ANB"}, {MNE_INV, "INV"},
00028     {MNE_MPS, "MPS"}, {MNE_MRD, "MRD"}, {MNE_MPP, "MPP"},
00029     {MNE_OUT, "OUT"}, {MNE_SET, "SET"}, {MNE_RST, "RST"},
00030 };
00031 
00032 struct EXP_str {
00033     eEXPRESSION exp;
00034     char str[3];
00035 };
00036 
00037 #define IL_EXP_NUM 10
00038 static const struct EXP_str exp_str[IL_EXP_NUM] = {
00039     {EXP_EQ, "=="}, {EXP_EQ, "="}, {EXP_NE, "!="}, {EXP_NE, "<>"},
00040     {EXP_LT, "<="}, {EXP_LE, "<"}, {EXP_GT, ">"}, {EXP_GE, ">="},
00041     {EXP_MOD, "%"}, {EXP_NMOD, "!%"},
00042 };
00043 
00044 
00045 ILinterpreter::ILinterpreter () {
00046     il_count = 0;
00047     memset(&inout, 0, sizeof(inout));
00048     inout.sec = time(NULL) + (60 * 60 * 9);
00049     inout_old = inout;
00050     cb_input = NULL;
00051     cb_output = NULL;
00052 }
00053 
00054 // input relay, expression
00055 int ILinterpreter::input (tInOut *io, int i, int old) {
00056     int keynum;
00057     float value, check;
00058     struct tm *tim;
00059 
00060     tim = localtime(&io->sec);
00061     keynum = il[i].keynum;
00062     // right value
00063     check = il[i].value;
00064 
00065     // left value
00066     value = 0;
00067     switch (il[i].key) {
00068 
00069     case 'y':
00070         value = tim->tm_year + 1900;
00071         break;
00072     case 'm':
00073         value = tim->tm_mon + 1;
00074         break;
00075     case 'd':
00076         value = tim->tm_mday;
00077         break;
00078     case 'h':
00079         value = tim->tm_hour;
00080         break;
00081     case 'i':
00082         value = tim->tm_min;
00083         break;
00084     case 's':
00085         value = tim->tm_sec;
00086         break;
00087 
00088     case '0':
00089         value = 0;
00090         break;
00091     case '1':
00092         value = 1;
00093         break;
00094 
00095     case 'M': // RELAY
00096         if (keynum >= IL_RELAY_NUM) break;
00097         value = io->relay[keynum];
00098         break;
00099 
00100     case 'T': // Timer
00101         if (keynum >= IL_TIMER_NUM) break;
00102         if (il[i].expression == EXP_NULL) {
00103             value = io->timer_flg[keynum] && io->timer_set[keynum] && io->timer_cnt[keynum] >= io->timer_set[keynum];
00104         } else {
00105             value = (float)io->timer_cnt[keynum] / 10.0;
00106         }
00107         break;
00108 
00109     case 'C': // Counter
00110         if (keynum >= IL_COUNTER_NUM) break;
00111         if (il[i].expression == EXP_NULL) {
00112              value = io->count_cnt[keynum] >= io->count_set[keynum];
00113         } else {
00114              value = io->count_cnt[keynum];
00115         }
00116         break;
00117 
00118     default: // order input
00119         if (cb_input) {
00120             value = (*cb_input)(il[i].key, keynum, il[i].expression, old);
00121         }
00122         break;
00123     }
00124 
00125     // expression
00126     switch (il[i].expression) {
00127     case EXP_EQ:
00128         return value == check;
00129     case EXP_NE:
00130         return value != check;
00131     case EXP_LE:
00132         return value <= check;
00133     case EXP_LT:
00134         return value < check;
00135     case EXP_GE:
00136         return value >= check;
00137     case EXP_GT:
00138         return value > check;
00139     case EXP_MOD:
00140         return (int)value % (int)check;
00141     case EXP_NMOD:
00142         return ! ((int)value % (int)check);
00143     }
00144 
00145     return value != 0;
00146 }
00147 
00148 // output relay
00149 void ILinterpreter::output (int i, int reg, eMNEMONIC mne) {
00150     int keynum;
00151 
00152     keynum = il[i].keynum;
00153 #ifdef DEBUG
00154     printf("output [%c%d] reg=%d sr=%d\r\n", il[i].key, keynum, reg, mne);
00155 #endif
00156 
00157     switch (il[i].key) {
00158     case 'M': // relay
00159         if (keynum >= IL_RELAY_NUM) break;
00160         if (mne == MNE_OUT) {
00161             inout.relay[keynum] = reg;
00162         } else
00163         if (mne == MNE_SET && reg) {
00164             inout.relay[keynum] = 1;
00165         } else
00166         if (mne == MNE_RST && reg) {
00167             inout.relay[keynum] = 0;
00168         }
00169         break;
00170 
00171     case 'T': // Timer
00172         if (keynum >= IL_TIMER_NUM) break;
00173         if (mne == MNE_OUT) {
00174             if (! inout.timer_flg[keynum]) {
00175                 // set timer
00176                 inout.timer_cnt[keynum] = 0;
00177             }
00178             inout.timer_flg[keynum] = reg;
00179         } else
00180         if (mne == MNE_RST && reg) {
00181             inout.timer_cnt[keynum] = 0;
00182         }
00183         break;
00184 
00185     case 'C': // Counter
00186         if (keynum >= IL_COUNTER_NUM) break;
00187         if (mne == MNE_OUT && reg) {
00188             if (inout.count_rev[keynum]) {
00189                 inout.count_cnt[keynum] --;
00190             } else {
00191                 inout.count_cnt[keynum] ++;
00192             }
00193         } else
00194         if (mne == MNE_RST && reg) {
00195             inout.count_cnt[keynum] = 0;
00196         }
00197     case 'R': // Counter (reverse)
00198         if (keynum >= IL_COUNTER_NUM) break;
00199         if (mne == MNE_OUT) {
00200             inout.count_rev[keynum] = reg;
00201         }
00202         break;
00203 
00204     default: // order output
00205         if (cb_output) {
00206             (*cb_output)(il[i].key, keynum, reg, mne);
00207         }
00208         break;
00209     }
00210 }
00211 
00212 // execute IL
00213 int ILinterpreter::exec () {
00214     int i, j, reg = -1;
00215     tInOut inout_tmp;
00216 
00217     if (! il_count) return 0;
00218 
00219     addr = 0;
00220     inout.sec = time(NULL);
00221     inout_tmp = inout;
00222 #ifdef DEBUG
00223     printf("timer0=%d(%d) timer1=%d(%d)\r\n", inout.timer_cnt[0], inout.timer_set[0], inout.timer_cnt[1], inout.timer_set[1]);
00224 #endif
00225 
00226     // mnemonic decode
00227     for(i = 0; i < il_count; i ++) {
00228         switch (il[i].mnemonic) {
00229         case MNE_LD:
00230             push(reg);
00231             reg = input(&inout, i);
00232             break;
00233         case MNE_LDI:
00234             push(reg);
00235             reg = ! input(&inout, i);
00236             break;
00237         case MNE_LDP:
00238             push(reg);
00239             reg = input(&inout, i) && ! input(&inout_old, i, 1);
00240             break;
00241         case MNE_LDF:
00242             push(reg);
00243             reg = ! input(&inout, i) && input(&inout_old, i, 1);
00244             break;
00245 
00246         case MNE_AND:
00247             reg = reg && input(&inout, i);
00248             break;
00249         case MNE_ANI:
00250             reg = reg && ! input(&inout, i);
00251             break;
00252         case MNE_ANDP:
00253             reg = reg && (input(&inout, i) && ! input(&inout_old, i, 1));
00254             break;
00255         case MNE_ANDF:
00256             reg = reg && (! input(&inout, i) && input(&inout_old, i, 1));
00257             break;
00258 
00259         case MNE_OR:
00260             reg = reg || input(&inout, i);
00261             break;
00262         case MNE_ORI:
00263             reg = reg || ! input(&inout, i);
00264             break;
00265         case MNE_ORP:
00266             reg = reg || (input(&inout, i) && ! input(&inout_old, i, 1));
00267             break;
00268         case MNE_ORF:
00269             reg = reg || (! input(&inout, i) && input(&inout_old, i, 1));
00270             break;
00271 
00272         case MNE_ANB:
00273             if (pop(&j) || j == -1) return -1;
00274             reg = reg && j;
00275             break;
00276         case MNE_ORB:
00277             if (pop(&j) || j == -1) return -1;
00278             reg = reg || j;
00279             break;
00280 
00281         case MNE_INV:
00282             reg = ! reg;
00283             break;
00284 
00285         case MNE_MPS:
00286             if (push(reg)) return -1;
00287             break;
00288         case MNE_MRD:
00289             if (read(&reg) || reg == -1) return -1;
00290             break;
00291         case MNE_MPP:
00292             if (pop(&reg) || reg == -1) return -1;
00293             break;
00294 
00295         case MNE_OUT:
00296         case MNE_SET:
00297         case MNE_RST:
00298             output(i, reg, il[i].mnemonic);
00299             break;
00300         }
00301     }
00302 
00303     inout_old = inout_tmp;
00304 
00305     return 0;
00306 }
00307 
00308 // set callback function
00309 struct tInOut* ILinterpreter::attach (float (*pf_i)(char, int, eEXPRESSION, int), void (*pf_o)(char, int, int, eMNEMONIC)) {
00310     cb_input = pf_i;
00311     cb_output = pf_o;
00312     return &inout;
00313 }
00314 
00315 // timer 10Hz
00316 void ILinterpreter::pool () {
00317     int i;
00318 
00319     if (! il_count) return;
00320 
00321     // timer
00322     for (i = 0; i < IL_TIMER_NUM; i ++) {
00323         if (inout.timer_flg[i] && inout.timer_cnt[i] < inout.timer_set[i]) {
00324             inout.timer_cnt[i] ++;
00325         }
00326     }
00327 }
00328 
00329 // load sub
00330 void ILinterpreter::load_exp (int i, char *buf) {
00331     int j, len;
00332     char *tmp;
00333 
00334     // MNEMONIC "KEY""num"==value
00335     il[i].key = buf[0];
00336     il[i].keynum = strtol(&buf[1], &tmp, 10);
00337     il[i].expression = EXP_NULL;
00338     il[i].value = 0;
00339 
00340     if (tmp) {
00341         // expression
00342         for (j = 0; j < IL_EXP_NUM; j ++) {
00343             len = strlen(exp_str[j].str);
00344             if (strncmp(tmp, exp_str[j].str, len) == 0 && tmp[len] >= '0' && tmp[len] <= '9') {
00345                 // MNEMONIC KEYnum"==""value"
00346                 il[i].expression = exp_str[j].exp;
00347                 il[i].value = atof(&tmp[len]);
00348                 break;
00349             }
00350         }
00351     }
00352 }
00353 
00354 // load IL file
00355 int ILinterpreter::load (char *file) {
00356     FILE *fp;
00357     char c;
00358     int i, j, len;
00359     char buf[20];
00360 
00361     il_count = 0;
00362 
00363     fp = fopen(file, "r");
00364     if (fp == NULL) return -1;
00365 
00366     i = 0;
00367     for (;;) {
00368         if (il_count >= IL_NUM) break;
00369         c = fgetc(fp);
00370         if (feof(fp)) break;
00371 
00372         if (c != '\r' && c != '\n' && i < 40 - 1) {
00373             // load
00374             buf[i] = c;
00375             i ++;
00376             continue;
00377         }
00378         buf[i] = 0;
00379         
00380         if (i == 0 || buf[0] == '#' || buf[0] == ';') {
00381             // comment
00382             i = 0;
00383             continue;
00384         }
00385 
00386         // mnemonic
00387         for (j = 0; j < IL_MNE_NUM; j ++) {
00388             len = strlen(mne_str[j].str);
00389             if (strncmp(buf, mne_str[j].str, len) == 0 && (buf[len] == ' ' || buf[len] == 0)) {
00390                 // "MNEMONIC" KEYnum==value
00391                 il[il_count].mnemonic = mne_str[j].mne;
00392                 load_exp(il_count, &buf[len + 1]);
00393 #ifdef DEBUG
00394                 printf("%d: M=%d [%c%d] E=%d V=%f\r\n", il_count, il[il_count].mnemonic, il[il_count].key, il[il_count].keynum, il[il_count].expression, il[il_count].value);
00395 #endif
00396                 il_count ++;
00397                 break;
00398             }
00399         }
00400         if (strncmp(buf, "END", 3) == 0) break;
00401         if (j == IL_MNE_NUM) return -1;
00402 
00403         i = 0;
00404     }
00405 
00406     // init
00407     for (i = 0; i < il_count; i ++) {
00408       if (il[i].mnemonic == MNE_DEF) {
00409         switch (il[i].key) {
00410         case 'T': // Timer
00411             inout.timer_set[il[i].keynum] = (int)il[i].value * 10;
00412             break;
00413 
00414         case 'C': // Counter
00415             inout.count_set[il[i].keynum] = (int)il[i].value;
00416             break;
00417         }
00418       }
00419     }
00420 
00421     fclose(fp);
00422 
00423     return il_count;
00424 }
00425 
00426 int ILinterpreter::push (int dat) {
00427 
00428     if (addr >= IL_STACK) {
00429         return -1;
00430     }
00431     stack[addr] = dat;
00432     addr ++;
00433     return dat;
00434 }
00435 
00436 int ILinterpreter::pop (int *dat) {
00437 
00438     if (addr == 0) {
00439         return -1;
00440     }
00441     addr --;
00442     *dat = stack[addr];
00443     return 0;
00444 }
00445 
00446 int ILinterpreter::read (int *dat) {
00447 
00448     if (addr == 0) {
00449         return -1;
00450     }
00451     *dat = stack[addr];
00452     return 0;
00453 }