うおーるぼっと版 豊四季タイニーBASIC

Dependencies:   BufferSerial Servo TB6612FNG2 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ttbasic.cpp Source File

ttbasic.cpp

00001 /*
00002     TOYOSHIKI TinyBASIC V1.0
00003     Reference source
00004     (C)2012 Tetsuya Suzuki, All rights reserved.
00005 */
00006 
00007 // Compiler requires description
00008 //#include <stdlib.h>
00009 //#include "sci.h"
00010 #include "mbed.h"
00011 #include "BufferSerial.h"
00012 #include "Servo.h"
00013 #include "TB6612.h"
00014 
00015 LocalFileSystem local("local");               // Create the local filesystem under the name "local"
00016 BufferSerial pc(USBTX, USBRX, 2000);
00017 //BufferSerial pc(p9, p10, 2000);
00018 Servo servo0(p25);
00019 Servo servo1(p26);
00020 TB6612 left(p21,p12,p11);
00021 TB6612 right(p22,p14,p13);
00022 DigitalOut out0(LED1);
00023 DigitalOut out1(LED2);
00024 DigitalOut out2(LED3);
00025 DigitalOut out3(LED4);
00026 DigitalIn in0(p29);         //SW2
00027 DigitalIn in1(p30);         //SW3
00028 AnalogIn ain0(p15);         //Photo0
00029 AnalogIn ain1(p16);         //Photo1
00030 AnalogIn ain2(p17);         //Photo2
00031 AnalogIn ain3(p18);         //Photo3
00032 
00033 void io_init()
00034 {
00035     pc.baud(115200);
00036     in0.mode(PullUp);
00037     in1.mode(PullUp);
00038     out0 = 0;    out1 = 0;    out2 = 0;    out3 = 0;
00039     servo0.calibrate(0.0009,180.0);
00040     servo1.calibrate(0.0009,180.0);
00041 //  servo0.calibrate(0.0006,180.0);    //RS306MD
00042 //  servo1.calibrate(0.0006,180.0);    //RS306MD
00043     servo0 = 0.5;    servo1 = 0.5;
00044     left = 0;
00045     right = 0;
00046 
00047 }
00048 
00049 // Depending on device functions
00050 // TO-DO Rewrite these functions to fit your machine
00051 // And see 'getrnd()'
00052 //void c_putch(char c){putch2(c);}
00053 //char c_getch(){return getch2();}
00054 //char c_kbhit(){return(kbhit2());}
00055 void c_putch(char c){pc.putc(c);}
00056 char c_getch(){return pc.getc();}
00057 char c_kbhit(){return(pc.readable());}
00058 void newline(void){
00059     c_putch(13); //CR
00060     c_putch(10); //LF
00061 }
00062 
00063 // TOYOSHIKI TinyBASIC symbols
00064 // TO-DO Rewrite defined values to fit your machine as needed
00065 #define SIZE_LINE 64 //Command line buffer length + NULL
00066 #define SIZE_IBUF 64 //i-code conversion buffer size
00067 #define SIZE_LIST 1024 //List buffer size
00068 #define SIZE_ARRY 32 //Array area size
00069 #define SIZE_GSTK 6 //GOSUB stack size(2/nest)
00070 #define SIZE_LSTK 15 //FOR stack size(5/nest)
00071 
00072 // RAM mapping
00073 char lbuf[SIZE_LINE]; //Command line buffer
00074 unsigned char ibuf[SIZE_IBUF]; //i-code conversion buffer
00075 short var[26]; //Variable area
00076 short arr[SIZE_ARRY]; //Array area
00077 unsigned char listbuf[SIZE_LIST]; //List area
00078 unsigned char* clp; //Pointer current line
00079 unsigned char* cip; //Pointer current Intermediate code
00080 unsigned char* gstk[SIZE_GSTK]; //GOSUB stack
00081 unsigned char gstki; //GOSUB stack index
00082 unsigned char* lstk[SIZE_LSTK]; //FOR stack
00083 unsigned char lstki; //FOR stack index
00084 
00085 // Prototypes (necessity minimum)
00086 short iexp(void);
00087 
00088 // Keyword table
00089 const char* kwtbl[] = {
00090     "GOTO", "GOSUB", "RETURN",
00091     "FOR", "TO", "STEP", "NEXT",
00092     "IF", "REM", "STOP",
00093 //  "INPUT", "PRINT", "LET",
00094     "INPUT", "PRINT", "OUT", "SERVO", "WAIT", "MOVE", "LET",
00095     ",", ";",
00096     "-", "+", "*", "/", "(", ")",
00097     ">=", "#", ">", "=", "<=", "<",
00098 //  "@", "RND", "ABS", "SIZE",
00099     "@", "RND", "ABS", "INP", "AIN", "SIZE",
00100 //  "LIST", "RUN", "NEW"
00101     "LIST", "RUN", "LOAD", "NEW"
00102 };
00103 
00104 // Keyword count
00105 #define SIZE_KWTBL (sizeof(kwtbl) / sizeof(const char*))
00106 
00107 // i-code(Intermediate code) assignment
00108 enum{
00109     I_GOTO, I_GOSUB, I_RETURN,
00110     I_FOR, I_TO, I_STEP, I_NEXT,
00111     I_IF, I_REM, I_STOP,
00112 //  I_INPUT, I_PRINT, I_LET,
00113     I_INPUT, I_PRINT, I_OUT, I_SERVO, I_WAIT, I_MOVE, I_LET,
00114     I_COMMA, I_SEMI,
00115     I_MINUS, I_PLUS, I_MUL, I_DIV, I_OPEN, I_CLOSE,
00116     I_GTE, I_SHARP, I_GT, I_EQ, I_LTE, I_LT,
00117 //  I_ARRAY, I_RND, I_ABS, I_SIZE,
00118     I_ARRAY, I_RND, I_ABS, I_INP, I_AIN, I_SIZE,
00119 //  I_LIST, I_RUN, I_NEW,
00120     I_LIST, I_RUN, I_LOAD, I_NEW,
00121     I_NUM, I_VAR, I_STR,
00122     I_EOL
00123 };
00124 
00125 // List formatting condition
00126 #define IS_OP(p) (p >= I_MINUS && p <= I_LT) // Operator style
00127 #define IS_SEP(p) (p == I_COMMA || p == I_SEMI) // Separator style
00128 #define IS_TOKSP(p) (/*p >= I_GOTO && */p <= I_LET && p != I_RETURN) // Token style
00129 
00130 // Error messages
00131 unsigned char err;// Error message index
00132 const char* errmsg[] ={
00133     "OK",
00134     "Devision by zero",
00135     "Overflow",
00136     "Subscript out of range",
00137     "Icode buffer full",
00138     "List full",
00139     "GOSUB too many nested",
00140     "RETURN stack underflow",
00141     "FOR too many nested",
00142     "NEXT without FOR",
00143     "NEXT without counter",
00144     "NEXT mismatch FOR",
00145     "FOR without variable",
00146     "FOR without TO",
00147     "LET without variable",
00148     "IF without condition",
00149     "Undefined line number",
00150     "\'(\' or \')\' expected",
00151     "\'=\' expected",
00152     "Illegal command",
00153     "Syntax error",
00154     "Internal error",
00155     "Abort by [ESC]"
00156 };
00157 
00158 // Error code assignment
00159 enum{
00160     ERR_OK,
00161     ERR_DIVBY0,
00162     ERR_VOF,
00163     ERR_SOL,
00164     ERR_IBUFOF,
00165     ERR_LBUFOF,
00166     ERR_GSTKOF,
00167     ERR_GSTKUF,
00168     ERR_LSTKOF,
00169     ERR_LSTKUF,
00170     ERR_NEXTWOV,
00171     ERR_NEXTUM,
00172     ERR_FORWOV,
00173     ERR_FORWOTO,
00174     ERR_LETWOV,
00175     ERR_IFWOC,
00176     ERR_ULN,
00177     ERR_PAREN,
00178     ERR_VWOEQ,
00179     ERR_COM,
00180     ERR_SYNTAX,
00181     ERR_SYS,
00182     ERR_ESC
00183 };
00184 
00185 // Standard C libraly (about same) functions
00186 char c_toupper(char c) {return(c <= 'z' && c >= 'a' ? c - 32 : c);}
00187 char c_isprint(char c) {return(c >= 32  && c <= 126);}
00188 char c_isspace(char c) {return(c <= ' ' &&(c == ' ' || (c <= 13 && c >= 9)));}
00189 char c_isdigit(char c) {return(c <= '9' && c >= '0');}
00190 char c_isalpha(char c) {return ((c <= 'z' && c >= 'a') || (c <= 'Z' && c >= 'A'));}
00191 char* c_strchr(char *s, char c){
00192     while(*s) {
00193         if(*s == c) return (s);
00194     ++s;
00195     }
00196     return NULL;
00197 }
00198 void c_puts(const char *s) {while(*s) c_putch(*s++);}
00199 void c_gets(){
00200     char c;
00201     unsigned char len;
00202 
00203     len = 0;
00204     while((c = c_getch()) != 13){
00205         if( c == 9) c = ' '; // TAB exchange Space
00206         if((c == 8) && (len > 0)){ // Backspace manipulation
00207             len--;
00208             c_putch(8); c_putch(' '); c_putch(8);
00209         } else
00210         if(c_isprint(c) && (len < (SIZE_LINE - 1))){
00211             lbuf[len++] = c;
00212             c_putch(c);
00213         }
00214     }
00215     newline();
00216     lbuf[len] = 0; // Put NULL
00217 
00218     if(len > 0){
00219         while(c_isspace(lbuf[--len])); // Skip space
00220         lbuf[++len] = 0; // Put NULL
00221     }
00222 }
00223 
00224 // GOSUB-RETURN stack
00225 void gpush(unsigned char* pd){
00226     if(gstki < SIZE_GSTK){
00227         gstk[gstki++] = pd;
00228         return;
00229     }
00230     err = ERR_GSTKOF;
00231 }
00232 
00233 unsigned char* gpop(){
00234     if(gstki > 0){
00235         return gstk[--gstki];
00236     }
00237     err = ERR_GSTKUF;
00238     return NULL;
00239 }
00240 
00241 // FOR-NEXT stack
00242 void lpush(unsigned char* pd){
00243     if(lstki < SIZE_LSTK){
00244         lstk[lstki++] = pd;
00245         return;
00246     }
00247     err = ERR_LSTKOF;
00248 }
00249 
00250 unsigned char* lpop(){
00251     if(lstki > 0){
00252         return lstk[--lstki];
00253     }
00254     err = ERR_LSTKUF;
00255     return NULL;
00256 }
00257 
00258 // Print OK or error message
00259 void error()
00260 {
00261     newline();
00262     c_puts(errmsg[err]);
00263     newline();
00264     err = 0;
00265 }
00266 
00267 // Print numeric specified columns
00268 void putnum(short value, short d){
00269     unsigned char i;
00270     unsigned char sign;
00271 
00272     if(value < 0){
00273         sign = 1;
00274         value = -value;
00275     } else {
00276         sign = 0;
00277     }
00278 
00279     lbuf[6] = 0;
00280     i = 6;
00281     do {
00282         lbuf[--i] = (value % 10) + '0';
00283         value /= 10;
00284     } while(value > 0);
00285 
00286     if(sign)
00287         lbuf[--i] = '-';
00288 
00289     //String length = 6 - i
00290     while(6 - i < d){ // If short
00291         c_putch(' '); // Fill space
00292         d--;
00293     }
00294     c_puts(&lbuf[i]);
00295 }
00296 
00297 // Input numeric and return value
00298 // Called by only INPUT statement
00299 short getnum(){
00300     short value, tmp;
00301     char c;
00302     unsigned char len;
00303     unsigned char sign;
00304 
00305     len = 0;
00306     while((c = c_getch()) != 13){
00307         if((c == 8) && (len > 0)){ // Backspace manipulation
00308             len--;
00309             c_putch(8); c_putch(' '); c_putch(8);
00310         } else
00311         if( (len == 0 && (c == '+' || c == '-')) ||
00312             (len < 6 && c_isdigit(c))){ // Numeric or sign only
00313             lbuf[len++] = c;
00314             c_putch(c);
00315         }
00316     }
00317     newline();
00318     lbuf[len] = 0;
00319 
00320     switch(lbuf[0]){
00321     case '-':
00322         sign = 1;
00323         len = 1;
00324         break;
00325     case '+':
00326         sign = 0;
00327         len = 1;
00328         break;
00329     default:
00330         sign = 0;
00331         len = 0;
00332         break;
00333     }
00334 
00335     value = 0; // Initialize value
00336     tmp = 0; // Temp value
00337     while(lbuf[len]){
00338         tmp = 10 * value + lbuf[len++] - '0';
00339         if(value > tmp){ // It means overflow
00340             err = ERR_VOF;
00341         }
00342         value = tmp;
00343     }
00344     if(sign)
00345         return -value;
00346     return value;
00347 }
00348 
00349 // Byte X,L,H -> Short HL
00350 // Used to get line number or I_NUM value
00351 short getvalue(unsigned char* ip){
00352     if(*ip == 0)
00353         return 32767; // Case X = 0
00354     return((short)*(ip + 1) + ((short)*(ip + 2) << 8));
00355 }
00356 
00357 // Get argument in parenthesis
00358 short getparam(){
00359     short value;
00360 
00361     if(*cip != I_OPEN){
00362         err = ERR_PAREN;
00363         return 0;
00364     }
00365     cip++;
00366     value = iexp();
00367     if(err) return 0;
00368 
00369     if(*cip != I_CLOSE){
00370         err = ERR_PAREN;
00371         return 0;
00372     }
00373     cip++;
00374 
00375     return value;
00376 }
00377 
00378 // Search line by line number
00379 unsigned char* getlp(short lineno){
00380     unsigned char *lp;
00381 
00382     lp = listbuf;
00383     while(*lp){
00384         if(getvalue(lp) >= lineno)
00385             break;
00386         lp += *lp;
00387     }
00388     return lp;
00389 }
00390 
00391 // Convert token to i-code
00392 // Return byte length or 0
00393 unsigned char toktoi(){
00394     unsigned char i; // Loop counter(i-code sometime)
00395     unsigned char len; //byte counter
00396     short value;
00397     short tmp;
00398     char* pkw; // Temporary keyword pointer
00399     char* ptok; // Temporary token pointer
00400     char c; // Surround the string character, " or '
00401     char* s; // Pointer to charactor at line buffer
00402 
00403     s = lbuf;
00404     len = 0; // Clear byte length
00405     while(*s){
00406         while(c_isspace(*s)) s++; // Skip space
00407 
00408         //Try keyword conversion
00409         for(i = 0; i < SIZE_KWTBL; i++){
00410             pkw = (char *)kwtbl[i]; // Point keyword
00411             ptok = s; // Point top of command line
00412             // Compare
00413             while((*pkw != 0) && (*pkw == c_toupper(*ptok))){
00414                 pkw++;
00415                 ptok++;
00416             }
00417             if(*pkw == 0){// Case success
00418                 // i have i-code
00419                 if(len >= SIZE_IBUF - 1){// List area full
00420                     err = ERR_IBUFOF;
00421                     return 0;
00422                 }
00423                 ibuf[len++] = i;
00424                 s = ptok;
00425                 break;
00426             }
00427         }
00428 
00429         // Case statement needs an argument except numeric, valiable, or strings
00430         switch(i){
00431         case I_REM:
00432             while(c_isspace(*s)) s++; // Skip space
00433             ptok = s;
00434             for(i = 0; *ptok++; i++); // Get length
00435             if(len >= SIZE_IBUF - 2 - i){
00436                 err = ERR_IBUFOF;
00437                 return 0;
00438             }
00439             ibuf[len++] = i; // Put length
00440             while(i--){ // Copy strings
00441                 ibuf[len++] = *s++;
00442             }
00443             return len;
00444         default:
00445             break;
00446         }
00447 
00448         if(*pkw != 0){ // Case not keyword
00449             ptok = s; // Point top of command line
00450 
00451             // Try numeric conversion
00452             if(c_isdigit(*ptok)){
00453                 value = 0;
00454                 tmp = 0;
00455                 do{
00456                     tmp = 10 * value + *ptok++ - '0';
00457                     if(value > tmp){
00458                         err = ERR_VOF;
00459                         return 0;
00460                     }
00461                     value = tmp;
00462                 } while(c_isdigit(*ptok));
00463 
00464                 if(len >= SIZE_IBUF - 3){
00465                     err = ERR_IBUFOF;
00466                     return 0;
00467                 }
00468                 s = ptok;
00469                 ibuf[len++] = I_NUM;
00470                 ibuf[len++] = value & 255;
00471                 ibuf[len++] = value >> 8;
00472             } else
00473 
00474             // Try valiable conversion
00475             if(c_isalpha(*ptok)){
00476                 if(len >= SIZE_IBUF - 2){
00477                     err = ERR_IBUFOF;
00478                     return 0;
00479                 }
00480                 if(len >= 2 && ibuf[len -2] == I_VAR){ // Case series of variables
00481                      err = ERR_SYNTAX; // Syntax error
00482                      return 0;
00483                 }
00484                 ibuf[len++] = I_VAR; // Put i-code
00485                 ibuf[len++] = c_toupper(*ptok) - 'A'; // Put index of valiable area
00486                 s++;
00487             } else
00488 
00489             // Try string conversion
00490             if(*s == '\"' || *s == '\''){// If start of string
00491                 c = *s;
00492                 s++; // Skip " or '
00493                 ptok = s;
00494                 for(i = 0; (*ptok != c) && c_isprint(*ptok); i++) // Get length
00495                     ptok++;
00496                 if(len >= SIZE_IBUF - 1 - i){ // List area full
00497                     err = ERR_IBUFOF;
00498                     return 0;
00499                 }
00500                 ibuf[len++] = I_STR; // Put i-code
00501                 ibuf[len++] = i; // Put length
00502                 while(i--){ // Put string
00503                     ibuf[len++] = *s++;
00504                 }
00505                 if(*s == c) s++; // Skip " or '
00506 
00507             // Nothing mutch
00508             } else {
00509                 err = ERR_SYNTAX;
00510                 return 0;
00511             }
00512         }
00513     }
00514     ibuf[len++] = I_EOL; // Put end of line
00515     return len; // Return byte length
00516 }
00517 
00518 //Listing 1 line of i-code
00519 void putlist(unsigned char* ip){
00520     unsigned char i;
00521     short value;
00522 
00523     while(*ip != I_EOL){
00524         // Case keyword
00525         if(*ip < SIZE_KWTBL){
00526             c_puts(kwtbl[*ip]);
00527             if(IS_TOKSP(*ip) || *ip == I_SEMI)c_putch(' ');
00528             if(*ip == I_REM){
00529                 ip++;
00530                 i = *ip++;
00531                 while(i--){
00532                     c_putch(*ip++);
00533                 }
00534                 return;
00535             }
00536             ip++;
00537         } else
00538 
00539         // Case numeric
00540         if(*ip == I_NUM){
00541             putnum(getvalue(ip), 0);
00542             ip += 3;
00543             if(!IS_OP(*ip) && !IS_SEP(*ip)) c_putch(' ');
00544         } else
00545 
00546         // Case valiable
00547         if(*ip == I_VAR){
00548             ip++;
00549             c_putch(*ip++ + 'A');
00550             if(!IS_OP(*ip) && !IS_SEP(*ip)) c_putch(' ');
00551         } else
00552 
00553         // Case string
00554         if(*ip == I_STR){
00555             ip++;
00556             value = 0;
00557             i = *ip;
00558             while(i--){
00559                 if(*(ip + i + 1) == '\"')
00560                     value = 1;
00561             }
00562             if(value) c_putch('\''); else c_putch('\"');
00563             i = *ip++;
00564             while(i--){
00565                 c_putch(*ip++);
00566             }
00567             if(value) c_putch('\''); else c_putch('\"');
00568 
00569         // Nothing match, I think, such case is impossible
00570         } else {
00571             err = ERR_SYS;
00572             return;
00573         }
00574     }
00575 }
00576 
00577 // Insert i-code to the list
00578 void inslist(){
00579     unsigned char len;
00580     unsigned char *lp1, *lp2;
00581 
00582     cip = ibuf;
00583     clp = getlp(getvalue(cip));
00584 
00585     lp1 = clp;
00586     if(getvalue(lp1) == getvalue(cip)){
00587         // Temporary measures of the case that
00588         // same line numbere exists and list area full,
00589         // existing line is deleted and new line is not inserted in.
00590 
00591         // if((getsize() - *lp1) < *cip){
00592         //  err = ERR_LBUFOF;
00593         //  return;
00594         // }
00595 
00596         lp2 = lp1 + *lp1;
00597         while((len = *lp2) != 0){
00598             while(len--){
00599                 *lp1++ = *lp2++;
00600             }
00601         }
00602         *lp1 = 0;
00603     }
00604 
00605     // Case line number only
00606     if(*cip == 4)
00607             return;
00608 
00609     // Check insertable
00610     while(*lp1){
00611         lp1 += *lp1;
00612     }
00613     if(*cip > (listbuf + SIZE_LIST - lp1 - 1)){
00614         err = ERR_LBUFOF;
00615         return;
00616     }
00617 
00618     // Make space
00619     len = lp1 - clp + 1;
00620     lp2 = lp1 + *cip;
00621     while(len--){
00622         *lp2-- = *lp1--;
00623     }
00624 
00625     // Insert
00626     len = *cip;
00627     while(len--){
00628         *clp++ = *cip++;
00629     }
00630 }
00631 //-------------------------------------------------------------
00632 short getinp(){
00633     short value1;
00634     short value2;
00635 
00636     value1 = getparam();
00637     if(err) return 0;
00638 
00639     if(value1 < 0) {
00640          err = ERR_SYNTAX;
00641         return 0;
00642     }
00643  
00644     switch(value1){
00645     case 0:
00646         value2 = in0;
00647         break;
00648     case 1:
00649         value2 = in1;
00650         break;
00651     default:
00652         err = ERR_SYNTAX;
00653         return 0;
00654     }
00655     return value2;
00656 }
00657 
00658 short getain(){
00659     short value1;
00660     short value2;
00661 
00662     value1 = getparam();
00663     if(err) return 0;
00664 
00665     if(value1 < 0) {
00666          err = ERR_SYNTAX;
00667         return 0;
00668     }
00669  
00670     switch(value1){
00671     case 0:
00672         value2 = ain0.read_u16();
00673         break;
00674     case 1:
00675         value2 = ain1.read_u16();
00676         break;
00677     case 2:
00678         value2 = ain2.read_u16();
00679         break;
00680     case 3:
00681         value2 = ain3.read_u16();
00682         break;
00683     default:
00684         err = ERR_SYNTAX;
00685         return 0;
00686     }
00687     return value2;
00688 }
00689 
00690 void iout(){
00691     short value1, value2;
00692 
00693     value1 = iexp();
00694     if(err) return ;
00695 
00696     if(*cip != I_COMMA){
00697         err = ERR_SYNTAX;
00698         return;
00699     }
00700     
00701     cip++;
00702     value2 = iexp();
00703     if(err) return ;
00704 
00705     if(value1 < 0) {
00706          err = ERR_SYNTAX;
00707         return;
00708     }
00709  
00710     switch(value1){
00711     case 0:
00712         out0 = value2 & 0x01;
00713         break;
00714     case 1:
00715         out1 = value2 & 0x01;
00716         break;
00717     case 2:
00718         out2 = value2 & 0x01;
00719         break;
00720     case 3:
00721         out3 = value2 & 0x01;
00722         break;
00723     default:
00724         err = ERR_SYNTAX;
00725         return ;
00726     }
00727 }
00728 
00729 void iservo(){
00730     short value1, value2;
00731 
00732     value1 = iexp();
00733     if(err) return ;
00734 
00735     if(*cip != I_COMMA){
00736         err = ERR_SYNTAX;
00737         return;
00738     }
00739     
00740     cip++;
00741     value2 = iexp();
00742     if(err) return ;
00743 
00744     if(value1 < 0) {
00745          err = ERR_SYNTAX;
00746         return;
00747     }
00748     if(value2 < 0) value2 = 0;
00749     if(value2 > 180) value2 = 180;
00750  
00751     switch(value1){
00752     case 0:
00753         servo0 = value2 / 180;
00754         break;
00755     case 1:
00756         servo1 = value2 / 180;
00757         break;
00758     default:
00759         err = ERR_SYNTAX;
00760         return ;
00761     }
00762 }
00763 
00764 void imove(){
00765     short value1, value2, value3;
00766 
00767     value1 = iexp();
00768     if(err) return ;
00769 
00770     if(*cip != I_COMMA){
00771         err = ERR_SYNTAX;
00772         return;
00773     }
00774     
00775     cip++;
00776     value2 = iexp();
00777     if(err) return ;
00778 
00779     if(*cip != I_COMMA){
00780         err = ERR_SYNTAX;
00781         return;
00782     }
00783     
00784     cip++;
00785     value3 = iexp();
00786     if(err) return ;
00787 
00788     if(value1 < -100) value1 = -100;
00789     if(value1 >  100) value1 =  100;
00790     if(value2 < -100) value2 = -100;
00791     if(value2 >  100) value2 =  100;
00792  
00793     if(value3 < 0) value3 = 0;
00794 
00795     left    = value1;
00796     right = value2;
00797     if(value3 > 0) wait_ms(value3);
00798  
00799 }
00800 
00801 int iload(char *filename) {
00802     FILE * fp;
00803     unsigned char len;
00804 
00805     fp = fopen( filename , "r" );
00806     if( fp == NULL ) {
00807         err = ERR_SYS;
00808         error();
00809         return -1;
00810     }
00811 
00812     while( fgets( lbuf , sizeof( lbuf ) , fp ) != NULL ) {
00813 //      puts(lbuf);
00814         int i = 0;
00815         while(*(lbuf + i)!=0x00)    //remove CR LF
00816         {
00817             if((*(lbuf + i) == 0x0a) || (*(lbuf + i) == 0x0d))
00818             {
00819                 *(lbuf + i) = 0x00;
00820             }
00821             i++;
00822         }
00823         len = toktoi(); // Convert token to i-code
00824         if(err){ // Error
00825             newline(); 
00826             c_puts("YOU TYPE:");
00827             c_puts(lbuf);
00828             error();
00829             fclose( fp );
00830             return -1;
00831         }
00832 
00833         if(*ibuf == I_NUM){ // Case the top includes line number
00834             *ibuf = len; // Change I_NUM to byte length
00835             inslist(); // Insert list
00836             if(err){
00837                 fclose( fp );
00838                 error(); // List buffer overflow
00839                 return -1;
00840             }
00841         } 
00842         else {
00843             fclose( fp );
00844             err = ERR_SYS;
00845             error(); // Print OK, and Clear error flag
00846             return -1;
00847         }
00848     }
00849     fclose( fp );
00850     return 0;
00851 }
00852 //-------------------------------------------------------------
00853 
00854 // Return free memory
00855 short getsize(){
00856     short value;
00857     unsigned char* lp;
00858 
00859     lp = listbuf;
00860     while(*lp){
00861         lp += *lp;
00862     }
00863 
00864     value = listbuf + SIZE_LIST - lp - 1;
00865     return value;
00866 }
00867 
00868 // Return Absolute value
00869 short getabs(){
00870     short value;
00871 
00872     value = getparam();
00873     if(err) return 0;
00874 
00875     if(value < 0) value *= -1;
00876     return value;
00877 }
00878 
00879 // Return random number
00880 // TO-DO Rewrite this function to fit your machine
00881 short getrnd(void){
00882     short value;
00883 
00884     value = getparam();
00885     if(err) return 0;
00886 
00887     return(rand() % value);
00888 }
00889 
00890 short getarray()
00891 {
00892     short index;
00893 
00894     index = getparam();
00895     if(err) return 0;
00896 
00897     if(index < SIZE_ARRY){
00898         return arr[index];
00899     } else {
00900         err = ERR_SOL;
00901         return 0;
00902     }
00903 }
00904 
00905 short ivalue(){
00906     short value;
00907 
00908     switch(*cip){
00909      case I_PLUS:
00910          cip++;
00911          value = ivalue();
00912          break;
00913      case I_MINUS:
00914          cip++;
00915          value = 0 - ivalue();
00916          break;
00917      case I_VAR:
00918          cip++;
00919          value = var[*cip++];
00920          break;
00921      case I_NUM:
00922          value = getvalue(cip);
00923          cip += 3;
00924          break;
00925      case I_ARRAY:
00926          cip++;
00927         value = getarray();
00928         break;
00929      case I_OPEN:
00930          value = getparam();
00931         break;
00932      case I_RND:
00933         cip++;
00934         value = getrnd();
00935         break;
00936      case I_ABS:
00937         cip++;
00938         value = getabs();
00939         break;
00940     case I_INP:
00941         cip++;
00942         value = getinp();
00943         break;
00944     case I_AIN:
00945         cip++;
00946         value = getain();
00947         break;
00948      case I_SIZE:
00949         cip++;
00950         if(*cip == I_OPEN){
00951             cip++;
00952             if(*cip == I_CLOSE)
00953                 cip++;
00954             else{
00955                 err = ERR_PAREN;
00956             }
00957         }
00958         value = getsize();
00959         break;
00960 
00961      default:
00962         value = 0;
00963         err = ERR_SYNTAX;
00964         break;
00965     }
00966     return value;
00967 }
00968 
00969 short icalc()
00970 {
00971     short value1, value2;
00972 
00973     value1 = ivalue();
00974 
00975     while(1){
00976         if(*cip == I_DIV){
00977             cip++;
00978             value2 = ivalue();
00979             if(value2 == 0){
00980                 err = ERR_DIVBY0;
00981                 break;
00982             }
00983             value1 /= value2;
00984         } else
00985         if(*cip == I_MUL){
00986             cip++;
00987             value2 = ivalue();
00988             value1 *= value2;
00989         } else {
00990             break;
00991         }
00992     }
00993     return value1;
00994 }
00995 
00996 short iexp()
00997 {
00998     short value1, value2;
00999 
01000     value1 = icalc();
01001 
01002     while(*cip == I_PLUS || *cip == I_MINUS){
01003         value2 = icalc();
01004         value1 += value2;
01005     }
01006     return value1;
01007 }
01008 
01009 void iprint(){
01010     short value;
01011     short len;
01012     unsigned char i;
01013 
01014     len = 0;
01015     while(1){
01016         switch(*cip){
01017         case I_SEMI:
01018         case I_EOL:
01019             break;
01020         case I_STR:
01021             cip++;
01022             i = *cip++;
01023             while(i--){
01024                 c_putch(*cip++);
01025             }
01026             break;
01027         case I_SHARP:
01028             cip++;
01029             len = iexp();
01030             if(err) return;
01031             break;
01032         default:
01033             value = iexp();
01034             if(err) return;
01035             putnum(value, len);
01036             break;
01037         }
01038 
01039         if(*cip == I_COMMA){
01040             cip++;
01041         }else{
01042             break;
01043         }
01044     };
01045     newline();
01046 }
01047 
01048 void iinput(){
01049     unsigned char i;
01050     short value;
01051     short index;
01052 
01053     while(1){
01054         switch(*cip){
01055         case I_STR:
01056             cip++;
01057             i = *cip++;
01058             while(i--){
01059                 c_putch(*cip++);
01060             }
01061             if(*cip == I_VAR){
01062                 cip++;
01063                 value = getnum();
01064                 var[*cip++] = value;
01065             } else
01066             if(*cip == I_ARRAY){
01067                 cip++;
01068                 index = getparam();
01069                 if(err) return;
01070                 if(index >= SIZE_ARRY){
01071                     err = ERR_SOL;
01072                     return;
01073                 }
01074                 value = getnum();
01075                 arr[index] = value;
01076             }
01077             break;
01078         case I_VAR:
01079             cip++;
01080             c_putch(*cip + 'A');
01081             c_putch(':');
01082             value = getnum();
01083             var[*cip++] = value;
01084             break;
01085         case I_ARRAY:
01086             cip++;
01087             index = getparam();
01088             if(err)
01089                 return;
01090             if(index >= SIZE_ARRY){
01091                 err = ERR_SOL;
01092                 return;
01093             }
01094             c_putch('@');c_putch('(');
01095             putnum(index,0);
01096             c_putch(')');c_putch(':');
01097             value = getnum();
01098             arr[index] = value;
01099             break;
01100         }
01101 
01102         switch(*cip){
01103         case I_COMMA:
01104             cip++;
01105             break;
01106         case I_SEMI:
01107         case I_EOL:
01108             return;
01109         default:
01110             err = ERR_SYNTAX;
01111             return;
01112         }
01113     }
01114 }
01115 
01116 //char iif(){
01117 signed char iif(){
01118     short value1, value2;
01119     unsigned char i;
01120     
01121     value1 = iexp();
01122     if(err) return -1;
01123 
01124     i = *cip++;
01125 
01126     value2 = iexp();
01127     if(err) return -1;
01128 
01129     switch(i){
01130     case I_EQ:
01131         return value1 == value2;
01132     case I_SHARP:
01133         return value1 != value2;
01134     case I_LT:
01135         return value1 <  value2;
01136     case I_LTE:
01137         return value1 <= value2;
01138     case I_GT:
01139         return value1 >  value2;
01140     case I_GTE:
01141         return value1 >= value2;
01142     default:
01143          err = ERR_IFWOC;
01144          return -1;
01145     }
01146 }
01147 
01148 void ivar(){
01149     short value;
01150     short index;
01151 
01152     index = *cip++;
01153     if(*cip == I_EQ){
01154         cip++;
01155         value = iexp();
01156         if(err) return;
01157     } else {
01158         err = ERR_VWOEQ;
01159         return;
01160     }
01161 
01162     if(index < 26){
01163         var[index] = value;
01164     } else {
01165         err = ERR_SOL;
01166     }
01167 }
01168 
01169 void iarray(){
01170     short value;
01171     short index;
01172 
01173     index = getparam();
01174     if(err) return;
01175     if(*cip == I_EQ){
01176         cip++;
01177         value = iexp();
01178         if(err) return;
01179     } else {
01180         err = ERR_VWOEQ;
01181         return;
01182     }
01183 
01184     if(index < SIZE_ARRY){
01185         arr[index] = value;
01186     } else {
01187         err = ERR_SOL;
01188     }
01189 }
01190 
01191 void ilet(){
01192     switch(*cip){
01193      case I_VAR:
01194         cip++;
01195         ivar();
01196         break;
01197     case I_ARRAY:
01198         cip++;
01199         iarray();
01200         break;
01201      default:
01202         err = ERR_LETWOV;
01203         break;
01204     }
01205 }
01206 
01207 void ilist(){
01208     short lineno;
01209 
01210     if(*cip == I_NUM){
01211         lineno = getvalue(cip);
01212         cip += 3;
01213     } else {
01214         lineno = 0;
01215     }
01216 
01217     for(    clp = listbuf;
01218             *clp && (getvalue(clp) < lineno);
01219             clp += *clp);
01220 
01221     while(*clp){
01222         putnum(getvalue(clp), 0);
01223         c_putch(' ');
01224         putlist(clp + 3);
01225         if(err){
01226             break;
01227         }
01228         newline();
01229         clp += *clp;
01230     }
01231 }
01232 
01233 void inew(void){
01234     unsigned char i;
01235 
01236     for(i = 0; i < 26; i++)
01237         var[i] = 0;
01238     gstki = 0;
01239     lstki = 0;
01240     *listbuf = 0;
01241     clp = listbuf;
01242 }
01243 
01244 unsigned char* iexe(){
01245     short lineno;
01246     unsigned char cd;
01247     unsigned char* lp;
01248     short vto, vstep;
01249     short index;
01250 
01251     while(1){
01252         if(c_kbhit()){
01253             if(c_getch() == 27){
01254                 while(*clp){
01255                     clp += *clp;
01256                 }
01257                 err = ERR_ESC;
01258                 return clp;
01259             }
01260         }
01261 
01262         switch(*cip){
01263         case I_GOTO:
01264             cip++;
01265             lineno = iexp();
01266             clp = getlp(lineno);
01267             if(lineno != getvalue(clp)){
01268                 err = ERR_ULN;
01269                 return NULL;
01270             }
01271             cip = clp + 3;
01272             continue;
01273         case I_GOSUB:
01274             cip++;
01275             lineno = iexp();
01276             if(err) return NULL;
01277             lp = getlp(lineno);
01278             if(lineno != getvalue(lp)){
01279                 err = ERR_ULN;
01280                 return NULL;
01281             }
01282             gpush(clp);
01283             gpush(cip);
01284             if(err) return NULL;
01285             clp = lp;
01286             cip = clp + 3;
01287             continue;
01288         case I_RETURN:
01289             cip = gpop();
01290             lp = gpop();
01291             if(err) return NULL;
01292             clp = lp;
01293             break;
01294         case I_FOR:
01295             cip++;
01296             if(*cip++ != I_VAR){
01297                 err = ERR_FORWOV;
01298                 return NULL;
01299             }
01300             index = *cip;
01301             ivar();
01302             if(err) return NULL;
01303 
01304             if(*cip == I_TO){
01305                 cip++;
01306                 vto = iexp();
01307             } else {
01308                 err = ERR_FORWOTO;
01309                 return NULL;
01310             }
01311             if(*cip == I_STEP){
01312                 cip++;
01313                 vstep = iexp();
01314             } else {
01315                 vstep = 1;
01316             }
01317 
01318             lpush(clp);
01319             lpush(cip);
01320             lpush((unsigned char*)vto);
01321             lpush((unsigned char*)vstep);
01322             lpush((unsigned char*)index);
01323             if(err) return NULL;
01324             break;
01325         case I_NEXT:
01326             cip++;
01327             if(*cip++ !=I_VAR){
01328                 err = ERR_NEXTWOV;
01329                 return NULL;
01330             }
01331 
01332             if(lstki < 5){
01333                 err = ERR_LSTKUF;
01334                 return NULL;
01335             }
01336             index = (short)lstk[lstki - 1];
01337             if(index != *cip){
01338                 err = ERR_NEXTUM;
01339                 return NULL;
01340             }
01341             cip++;
01342             vstep = (short)lstk[lstki - 2];
01343             var[index] += vstep;
01344 
01345             vto = (short)lstk[lstki - 3];
01346             if( ((vstep < 0) && (var[index] < vto)) ||
01347                 ((vstep > 0) && (var[index] > vto))){
01348                 lstki -= 5;
01349                 break;
01350             }
01351             cip = lstk[lstki - 4];
01352             clp = lstk[lstki - 5];
01353             continue;
01354 
01355         case I_IF:
01356             cip++;
01357             cd = iif();
01358             if(err){
01359                 err = ERR_IFWOC;
01360                 return NULL;
01361             }
01362             if(cd)
01363                 continue;
01364             // If false, same as REM
01365         case I_REM:
01366             // Seek pointer to I_EOL
01367             // No problem even if it points not realy end of line
01368             while(*cip != I_EOL) cip++;
01369             break;
01370         case I_STOP:
01371             while(*clp){
01372                 clp += *clp;
01373             }
01374             return clp;
01375         case I_INPUT:
01376             cip++;
01377             iinput();
01378             break;
01379         case I_PRINT:
01380             cip++;
01381             iprint();
01382             break;
01383         case I_LET:
01384             cip++;
01385             ilet();
01386             break;
01387         case I_OUT:
01388             cip++;
01389             iout();
01390             break;
01391         case I_SERVO:
01392             cip++;
01393             iservo();
01394             break;
01395         case I_MOVE:
01396             cip++;
01397             imove();
01398             break;
01399         case I_WAIT:
01400             cip++;
01401             int t = iexp();
01402             if(err) return NULL;
01403             if(t < 0) t = 0;
01404             wait_ms(t);
01405             break;
01406         case I_VAR:
01407             cip++;
01408             ivar();
01409             break;
01410         case I_ARRAY:
01411             cip++;
01412             iarray();
01413             break;
01414         case I_LIST:
01415         case I_NEW:
01416         case I_RUN:
01417             err = ERR_COM;
01418             return NULL;
01419         }
01420 
01421         switch(*cip){
01422         case I_SEMI:
01423             cip++;
01424             break;
01425         case I_EOL:
01426             return clp + *clp;
01427         default:
01428             err = ERR_SYNTAX;
01429             return NULL;
01430         }
01431     }
01432 }
01433 
01434 void irun(){
01435     unsigned char* lp;
01436 
01437     gstki = 0;
01438     lstki = 0;
01439     clp = listbuf;
01440     
01441     while(*clp){
01442         cip = clp + 3;
01443         lp = iexe();
01444         if(err)
01445             return;
01446         clp = lp;
01447     }
01448 }
01449 
01450 void icom(){
01451     cip = ibuf;
01452     switch(*cip){
01453     case I_LIST:
01454         cip++;
01455         if(*cip == I_EOL || *(cip + 3) == I_EOL)
01456             ilist();
01457         else
01458             err = ERR_SYNTAX;
01459         break;
01460     case I_NEW:
01461         cip++;
01462         if(*cip == I_EOL)
01463             inew();
01464         else
01465             err = ERR_SYNTAX;
01466         break;
01467       case I_LOAD:
01468         cip++;
01469         iload("/local/AUTO.BAS");
01470         break;
01471     case I_RUN:
01472         cip++;
01473         irun();
01474         break;
01475     default:
01476         iexe();
01477         break;
01478     }
01479 
01480     if(err && err != ERR_ESC){
01481         if(cip >= listbuf && cip < listbuf + SIZE_LIST && *clp)
01482         {
01483             newline(); c_puts("ERR LINE:");
01484             putnum(getvalue(clp), 0);
01485             c_putch(' ');
01486             putlist(clp + 3);
01487         }
01488         else
01489         {
01490             newline(); c_puts("YOU TYPE: ");
01491             putlist(ibuf);
01492         }
01493     }
01494     
01495 }
01496 
01497 void basic(){
01498     unsigned char len;
01499 
01500 //  sci2_init();
01501     io_init();
01502     inew();
01503     c_puts("TOYOSHIKI TINY BASIC"); newline();
01504 //    c_puts("PIC24F EDITION"); newline();
01505     c_puts("Wallbot EDITION"); newline();
01506     error(); // Print OK, and Clear error flag
01507 
01508     if(in0 == 0)    //Auto Load & Run
01509     {
01510         c_puts("Auto Load & Run");    
01511         newline();
01512         if(iload("/local/AUTO.BAS") == 0)
01513         {
01514             error(); // Print OK, and Clear error flag
01515             irun();
01516         }
01517         error(); // Print OK, and Clear error flag
01518     }
01519 
01520     // Input 1 line and execute
01521     while(1){
01522         c_putch('>');// Prompt
01523         c_gets(); // Input 1 line
01524         len = toktoi(); // Convert token to i-code
01525         if(err){ // Error
01526             newline(); c_puts("YOU TYPE:");
01527             c_puts(lbuf);
01528             error();
01529             continue; // Do nothing
01530         }
01531 
01532         if(*ibuf == I_NUM){ // Case the top includes line number
01533             *ibuf = len; // Change I_NUM to byte length
01534             inslist(); // Insert list
01535             if(err){
01536                 error(); // List buffer overflow
01537             }
01538         } else {
01539             icom(); // Execute direct
01540             error(); // Print OK, and Clear error flag
01541         }
01542     }
01543 }
01544 
01545