Embed:
(wiki syntax)
Show/hide line numbers
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 == -1) return -1; 00290 break; 00291 case MNE_MPP: 00292 if (pop(®) || 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 }
Generated on Thu Jul 21 2022 02:05:17 by 1.7.2