├── LICENSE ├── README.md ├── basic_blink ├── basic_blink.ino ├── config.ino ├── program.ino └── tny.ino └── develop ├── config.ino ├── develop.ino ├── lib.ino ├── program.ino └── tny.ino /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # atinybasic 2 | 3 | `atinybasic` is a straight-forward port of Dennis Allison's famous ["Tiny BASIC"](https://en.wikipedia.org/wiki/Tiny_BASIC) from ["The People's Computer Company"](https://en.wikipedia.org/wiki/People%27s_Computer_Company) [newsletter circa September 1975](https://archive.org/details/1975-09-peoples-computer-company). In the spirit of the original, `atinybasic` does not attempt to be a complete BASIC environment per se. Instead it's meant to be a starting point for building a BASIC suited for a particular project or task. I have added `RND`, `ABS` and an array to the basic feature set, but this is more to show how you might add more features than anything else. 4 | 5 | # Video 6 | 7 | [![Alt text](https://img.youtube.com/vi/GVN8z__guZE/0.jpg)](https://www.youtube.com/watch?v=GVN8z__guZE) 8 | 9 | # Installation 10 | 11 | Copy the `basic_blink` folder to where you keep your Arduino sketch folders. 12 | 13 | # Setup 14 | 15 | By default, the included `basic_blink` sketch will start a headless BASIC interpreter running a (flash stored) program that blinks the LED attached to pin 13 on Arduino Uno boards. To enable a serial console, change the `#define CONSOLE 0` line of `config.ino` to `#define CONSOLE 1`. Also change `#define RAM 0` to `#define RAM 1` and `#define FLASH 1` to `#define FLASH 0` (this changes the program source from being the onboard flash to the onboard RAM). 16 | 17 | # Size 18 | 19 | Headless, the interpreter only takes up 348 bytes of RAM, leaving the rest for BASIC programs themselves. 20 | -------------------------------------------------------------------------------- /basic_blink/basic_blink.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | prelude(); 3 | } 4 | 5 | void loop() { 6 | repl(); 7 | } 8 | -------------------------------------------------------------------------------- /basic_blink/config.ino: -------------------------------------------------------------------------------- 1 | #ifndef CONSOLE 2 | #define CONSOLE 0 3 | #endif 4 | 5 | #ifndef RAM 6 | #define RAM 0 7 | #endif 8 | 9 | #ifndef FLASH 10 | #define FLASH 1 11 | #endif 12 | 13 | #ifndef WIDTH 14 | #define WIDTH 81 15 | #endif 16 | 17 | #ifndef SIZE 18 | #define SIZE 1024 19 | #endif 20 | 21 | #ifndef STACKSIZE 22 | #define STACKSIZE 16 23 | #endif 24 | 25 | #ifndef MAX_POS 26 | #define MAX_POS 32767 27 | #endif 28 | 29 | #ifndef MAX_NEG 30 | #define MAX_NEG -32767 31 | #endif 32 | 33 | #ifndef X1 34 | #define X1 0 35 | #endif 36 | 37 | #ifndef X2 38 | #define X2 1 39 | #endif 40 | 41 | #ifndef X3 42 | #define X3 2 43 | #endif 44 | 45 | #ifndef X4 46 | #define X4 3 47 | #endif 48 | 49 | #ifndef X5 50 | #define X5 4 51 | #endif 52 | 53 | #ifndef X6 54 | #define X6 5 55 | #endif 56 | 57 | #ifndef X7 58 | #define X7 6 59 | #endif 60 | 61 | #ifndef X8 62 | #define X8 7 63 | #endif 64 | 65 | #ifndef X9 66 | #define X9 8 67 | #endif 68 | 69 | #ifndef X10 70 | #define X10 9 71 | #endif 72 | 73 | #ifndef X11 74 | #define X11 10 75 | #endif 76 | 77 | #ifndef X12 78 | #define X12 11 79 | #endif 80 | 81 | #ifndef X13 82 | #define X13 12 83 | #endif 84 | 85 | #ifndef X14 86 | #define X14 13 87 | #endif 88 | 89 | #ifndef X15 90 | #define X15 14 91 | #endif 92 | 93 | #ifndef X16 94 | #define X16 15 95 | #endif 96 | 97 | #ifndef X17 98 | #define X17 16 99 | #endif 100 | 101 | #ifndef X18 102 | #define X18 17 103 | #endif 104 | 105 | #ifndef X19 106 | #define X19 18 107 | #endif 108 | 109 | #ifndef X20 110 | #define X20 19 111 | #endif 112 | 113 | #ifndef SYNTAX_ERROR 114 | #define SYNTAX_ERROR 1 115 | #endif 116 | 117 | #ifndef MISSING_LINE 118 | #define MISSING_LINE 2 119 | #endif 120 | 121 | #ifndef LINE_NUMBER_TOO_LARGE 122 | #define LINE_NUMBER_TOO_LARGE 3 123 | #endif 124 | 125 | #ifndef TOO_MANY_GOSUBS 126 | #define TOO_MANY_GOSUBS 4 127 | #endif 128 | 129 | #ifndef RETURN_WITHOUT_GOSUB 130 | #define RETURN_WITHOUT_GOSUB 5 131 | #endif 132 | 133 | #ifndef EXPRESSION_TOO_COMPLEX 134 | #define EXPRESSION_TOO_COMPLEX 6 135 | #endif 136 | 137 | #ifndef TOO_MANY_LINES 138 | #define TOO_MANY_LINES 7 139 | #endif 140 | 141 | #ifndef DIVISION_BY_ZERO 142 | #define DIVISION_BY_ZERO 8 143 | #endif 144 | -------------------------------------------------------------------------------- /basic_blink/program.ino: -------------------------------------------------------------------------------- 1 | const PROGMEM int list[] = {100, 110, 120, 130, 140, 150, 160, 170, 180, 190}; 2 | const PROGMEM char bas[][WIDTH] = { 3 | {"100 LET L = 0\n"}, 4 | {"110 LET I = 0\n"}, 5 | {"120 LET I = I + 1\n"}, 6 | {"130 IF I > 1000 THEN GOTO 150\n"}, 7 | {"140 GOTO 120\n"}, 8 | {"150 IF L = 1 THEN GOTO 180\n"}, 9 | {"160 LET L = 1\n"}, 10 | {"170 GOTO 110\n"}, 11 | {"180 LET L = 0\n"}, 12 | {"190 GOTO 110\n"}, 13 | }; 14 | -------------------------------------------------------------------------------- /basic_blink/tny.ino: -------------------------------------------------------------------------------- 1 | int cur; 2 | int line_number; 3 | byte errno; 4 | 5 | void error() { 6 | #if CONSOLE == 1 7 | switch(errno) { 8 | case SYNTAX_ERROR: 9 | Serial.print(F("SYNTAX ERROR")); 10 | break; 11 | case MISSING_LINE: 12 | Serial.print(F("MISSING LINE")); 13 | break; 14 | case LINE_NUMBER_TOO_LARGE: 15 | Serial.print(F("LINE NUMBER TOO LARGE")); 16 | break; 17 | case TOO_MANY_GOSUBS: 18 | Serial.print(F("TOO MANY GOSUBS")); 19 | break; 20 | case RETURN_WITHOUT_GOSUB: 21 | Serial.print(F("RETURN WITHOUT GOSUB")); 22 | break; 23 | case EXPRESSION_TOO_COMPLEX: 24 | Serial.print(F("EXPRESSION TOO COMPLEX")); 25 | break; 26 | case TOO_MANY_LINES: 27 | Serial.print(F("TOO MANY LINES")); 28 | break; 29 | case DIVISION_BY_ZERO: 30 | Serial.print(F("DIVISION BY ZERO")); 31 | break; 32 | } 33 | Serial.print(F(": LINE: ")); 34 | Serial.print(line_number); 35 | Serial.print(F(" COL: ")); 36 | Serial.print(cur); 37 | Serial.print("\n"); 38 | #endif 39 | } 40 | 41 | int aestk[STACKSIZE]; 42 | byte aestk_ptr; 43 | 44 | int ctrlstk[STACKSIZE]; 45 | byte ctrlstk_ptr; 46 | 47 | int sbrstk[STACKSIZE]; 48 | byte sbrstk_ptr; 49 | 50 | char pgm[SIZE]; 51 | char lbuf[WIDTH]; 52 | 53 | int vars[26]; 54 | 55 | void il_init() { 56 | memset(pgm,'\n',SIZE); 57 | memset(vars,0,sizeof(int)*26); 58 | cur = 0; 59 | } 60 | 61 | void il_nline() { 62 | #if CONSOLE == 1 63 | Serial.print("\n"); 64 | #endif 65 | } 66 | 67 | byte getc() { 68 | #if CONSOLE == 1 69 | int data = Serial.read(); 70 | while (data == -1) data = Serial.read(); 71 | return data; 72 | #endif 73 | return 0; 74 | } 75 | 76 | int il_getline() { 77 | #if CONSOLE == 1 78 | cur = 0; 79 | char chr; 80 | unsigned char i; 81 | start: 82 | Serial.print("> "); 83 | i = 0; 84 | cur = 0; 85 | while((chr = getc()) && 86 | chr != '\n' && 87 | i < WIDTH) { 88 | if (chr == EOF) return 0; 89 | if (chr > 96 && chr < 123) chr = chr - 32; 90 | lbuf[i++] = chr; 91 | } 92 | if (i < 1) goto start; 93 | if (i >= WIDTH) { 94 | errno = EXPRESSION_TOO_COMPLEX; 95 | return 1; 96 | } 97 | lbuf[i] = '\n'; 98 | #else 99 | lbuf[0] = 'R'; 100 | lbuf[1] = 'U'; 101 | lbuf[2] = 'N'; 102 | lbuf[3] = '\n'; 103 | return 1; 104 | #endif 105 | } 106 | 107 | int il_tstl() { 108 | while(lbuf[cur] == ' ') cur++; 109 | if (lbuf[cur] > 47 && lbuf[cur] < 58) return 1; 110 | return 0; 111 | } 112 | 113 | int read_number(int* cur, char* line) { 114 | int num = 0; 115 | while(line[*cur] > 47 && line[*cur] < 58) { 116 | num = num * 10 + line[*cur] - 48; 117 | (*cur)++; 118 | } 119 | return num; 120 | } 121 | 122 | int load_nearest_line(int num) { 123 | if (RAM) { 124 | int start; 125 | int end; 126 | int oldln = find_ram_line(num,&start,&end); 127 | if (oldln < 1) return 0; 128 | memcpy(lbuf,pgm+start,end-start+1); 129 | cur = 0; 130 | return read_number(&cur,lbuf); 131 | } 132 | if (FLASH) { 133 | for (int i = 0; i < sizeof(list)/2; i++) { 134 | int line = pgm_read_word(list+i); 135 | if (line < num) continue; 136 | for (int j = 0; j < WIDTH; j++) { 137 | lbuf[j] = pgm_read_byte_near(bas[i]+j); 138 | if (pgm_read_byte_near(bas[i]+j) == '\n') break; 139 | } 140 | cur = 0; 141 | return read_number(&cur,lbuf); 142 | } 143 | return 0; 144 | } 145 | } 146 | 147 | int find_ram_line(int newln, int* start, int* end) { 148 | *start = 0; 149 | *end = 0; 150 | int oldln = -1; 151 | while(*end < SIZE) { 152 | if (pgm[*end] == '\n') { 153 | int cur = *start; 154 | oldln = read_number(&cur,pgm); 155 | if (oldln >= newln || oldln == 0) break; 156 | *start = *end+1; 157 | } 158 | (*end)++; 159 | } 160 | return oldln; 161 | } 162 | 163 | void il_insrt() { 164 | if (!RAM) return; 165 | int newln = read_number(&cur,lbuf); 166 | int start; 167 | int end; 168 | int oldln = find_ram_line(newln,&start,&end); 169 | if (oldln == newln) { 170 | memcpy(pgm+start,pgm+end+1,SIZE-(end+1)); 171 | } 172 | if (oldln >= newln && lbuf[cur] != '\n') { 173 | int mcur = cur; 174 | while (lbuf[mcur] != '\n') mcur++; 175 | memmove(pgm+start+mcur+1,pgm+start,SIZE-(start+mcur+1)); 176 | } 177 | if (lbuf[cur] != '\n') { 178 | while (lbuf[cur] != '\n') cur++; 179 | memcpy(pgm+start,lbuf,cur+1); 180 | } 181 | } 182 | 183 | void il_xinit() { 184 | aestk_ptr = 0; 185 | ctrlstk_ptr = 0; 186 | sbrstk_ptr = 0; 187 | line_number = 0; 188 | } 189 | 190 | int il_tst(const char* str) { 191 | int acur = cur; 192 | int bcur = 0; 193 | while(lbuf[acur] == ' ') acur++; 194 | while(str[bcur] == lbuf[acur]) { 195 | bcur++; 196 | acur++; 197 | }; 198 | if (str[bcur] != 0) return 0; 199 | cur = acur; 200 | return 1; 201 | } 202 | 203 | int il_tstv() { 204 | if (aestk_ptr == STACKSIZE) { 205 | errno = EXPRESSION_TOO_COMPLEX; 206 | return 0; 207 | } 208 | while(lbuf[cur] == ' ') cur++; 209 | if (lbuf[cur] < 65 || lbuf[cur] > 90) { 210 | errno = SYNTAX_ERROR; 211 | return 0; 212 | } 213 | aestk[aestk_ptr++] = lbuf[cur]-65; 214 | cur++; 215 | return 1; 216 | } 217 | 218 | void il_call(int lbl) { 219 | ctrlstk[ctrlstk_ptr++] = lbl; 220 | } 221 | 222 | void il_done() { 223 | while(lbuf[cur] == ' ') cur++; 224 | if (lbuf[cur] != '\n') errno = SYNTAX_ERROR; 225 | } 226 | 227 | void il_store() { 228 | int val = aestk[--aestk_ptr]; 229 | int idx = aestk[--aestk_ptr]; 230 | if (idx == 11) digitalWrite(13,val != 0); 231 | vars[idx] = val; 232 | } 233 | 234 | int il_nxt() { 235 | if (line_number == 0) return 0; 236 | line_number = load_nearest_line(line_number+1); 237 | if (line_number == 0) return 0; 238 | return 1; 239 | } 240 | 241 | void il_xfer() { 242 | line_number = aestk[--aestk_ptr]; 243 | line_number = load_nearest_line(line_number); 244 | } 245 | 246 | void il_sav() { 247 | sbrstk[sbrstk_ptr++] = line_number; 248 | } 249 | 250 | void il_prs() { 251 | #if CONSOLE == 1 252 | while(lbuf[cur] != '"') { 253 | if (lbuf[cur] == '\n') { 254 | errno = SYNTAX_ERROR; 255 | return; 256 | } 257 | Serial.print(lbuf[cur]); 258 | cur++; 259 | } 260 | cur++; 261 | #endif 262 | } 263 | 264 | void il_spc() { 265 | #if CONSOLE == 1 266 | Serial.print(" "); 267 | #endif 268 | } 269 | 270 | void il_prn() { 271 | #if CONSOLE == 1 272 | Serial.print(aestk[--aestk_ptr]); 273 | #else 274 | aestk[--aestk_ptr]; 275 | #endif 276 | } 277 | 278 | int il_cmpr() { 279 | int b = aestk[--aestk_ptr]; 280 | int rel = aestk[--aestk_ptr]; 281 | int a = aestk[--aestk_ptr]; 282 | switch(rel) { 283 | case 0: //= 284 | if (a == b) return 1; 285 | break; 286 | case 1: //< 287 | if (a < b) return 1; 288 | break; 289 | case 2: //<= 290 | if (a <= b) return 1; 291 | break; 292 | case 3: //<> 293 | if (a != b) return 1; 294 | break; 295 | case 4: //> 296 | if (a > b) return 1; 297 | break; 298 | case 5: //>= 299 | if (a >= b) return 1; 300 | break; 301 | } 302 | return 0; 303 | } 304 | 305 | void il_innum() { 306 | int num = 0; 307 | char chr; 308 | while((chr = getc()) && chr > 47 && chr < 58) { 309 | num = num * 10 + chr - 48; 310 | } 311 | aestk[aestk_ptr++] = num; 312 | } 313 | 314 | void il_rstr() { 315 | if (sbrstk_ptr == 0) { 316 | errno = RETURN_WITHOUT_GOSUB; 317 | return; 318 | } 319 | line_number = sbrstk[--sbrstk_ptr]; 320 | } 321 | 322 | void il_lst() { 323 | #if CONSOLE == 1 324 | int line = load_nearest_line(0); 325 | while (line != 0) { 326 | for (int i = 0; i < WIDTH ; i++) { 327 | char chr = lbuf[i]; 328 | if (chr == '\n') break; 329 | Serial.print(chr); 330 | } 331 | Serial.print("\n"); 332 | line = load_nearest_line(line+1); 333 | } 334 | #endif 335 | } 336 | 337 | void il_run() { 338 | aestk[aestk_ptr++] = load_nearest_line(0); 339 | } 340 | 341 | void il_neg() { 342 | aestk[aestk_ptr-1] = -1*aestk[aestk_ptr-1]; 343 | } 344 | 345 | void il_add() { 346 | int b = aestk[--aestk_ptr]; 347 | int a = aestk[--aestk_ptr]; 348 | aestk[aestk_ptr++] = a+b; 349 | } 350 | 351 | void il_sub() { 352 | int b = aestk[--aestk_ptr]; 353 | int a = aestk[--aestk_ptr]; 354 | aestk[aestk_ptr++] = a-b; 355 | } 356 | 357 | void il_mul() { 358 | int b = aestk[--aestk_ptr]; 359 | int a = aestk[--aestk_ptr]; 360 | aestk[aestk_ptr++] = a*b; 361 | } 362 | 363 | void il_div() { 364 | int b = aestk[--aestk_ptr]; 365 | int a = aestk[--aestk_ptr]; 366 | aestk[aestk_ptr++] = a/b; 367 | } 368 | 369 | void il_ind() { 370 | int i = aestk[--aestk_ptr]; 371 | aestk[aestk_ptr++] = vars[i]; 372 | } 373 | 374 | int il_tstn() { 375 | if (lbuf[cur] < 48 || lbuf[cur] > 57) return 0; 376 | aestk[aestk_ptr++] = read_number(&cur,lbuf); 377 | return 1; 378 | } 379 | 380 | void il_lit(int val) { 381 | aestk[aestk_ptr++] = val; 382 | } 383 | 384 | void il_sze() { 385 | int start; 386 | int end; 387 | find_ram_line(MAX_POS,&start,&end); 388 | aestk[aestk_ptr++] = SIZE-(end+2); //newline terminates program 389 | } 390 | 391 | void il_rnd() { 392 | aestk[aestk_ptr++] = random(1,aestk[--aestk_ptr]+1); 393 | } 394 | 395 | void il_abs() { 396 | int a = aestk[--aestk_ptr]; 397 | aestk[aestk_ptr++] = abs(a); 398 | } 399 | 400 | void il_get() { 401 | int size = aestk[--aestk_ptr]; 402 | int idx = aestk[--aestk_ptr]; 403 | aestk[aestk_ptr++] = ((int*) (pgm+SIZE-size))[idx]; 404 | } 405 | 406 | void il_set() { 407 | int size = aestk[--aestk_ptr]; 408 | int val = aestk[--aestk_ptr]; 409 | int idx = aestk[--aestk_ptr]; 410 | ((int*) (pgm+SIZE-size))[idx] = val; 411 | } 412 | 413 | void prelude() { 414 | pinMode(13,OUTPUT); 415 | #if CONSOLE == 1 416 | Serial.begin(9600); 417 | while (!Serial) {}; 418 | Serial.println(F("TINY BASIC FOR ARDUINO")); 419 | Serial.println(F("BY DENNIS ALLISON")); 420 | Serial.println(F("MODIFIED AND TRANSLATED BY TREVOR JAY")); 421 | Serial.println(F("2020")); 422 | Serial.println(F("@COPYLEFT")); 423 | Serial.println(F("ALL WRONGS RESERVED")); 424 | #endif 425 | } 426 | 427 | void repl() { 428 | start: il_init(); 429 | il_nline(); //errent? 430 | co: errno = 0; 431 | if(!il_getline()) goto stop; 432 | if (errno) goto error; 433 | if (!il_tstl()) goto xec; 434 | il_insrt(); 435 | goto co; 436 | xec: il_xinit(); 437 | stmt: 438 | if (!il_tst("LET")) goto s1; 439 | if (!il_tst("@(")) goto l1; 440 | il_call(X19); goto expr; 441 | x19: 442 | errno = 0; 443 | if (!il_tst(")")) errno = SYNTAX_ERROR; 444 | if (errno) goto error; 445 | errno = 0; 446 | if (!il_tst("=")) errno = SYNTAX_ERROR; 447 | if (errno) goto error; 448 | il_call(X20); goto expr; 449 | x20: errno = 0; 450 | il_done(); 451 | if (errno) goto error; 452 | il_sze(); 453 | il_set(); 454 | goto l2; 455 | l1: errno = 0; 456 | il_tstv(); 457 | if (errno) goto error; 458 | errno = 0; 459 | if (!il_tst("=")) errno = SYNTAX_ERROR; 460 | if (errno) goto error; 461 | il_call(X1); goto expr; 462 | x1: errno = 0; 463 | il_done(); 464 | if (errno) goto error; 465 | il_store(); 466 | l2: 467 | if (il_nxt()) goto stmt; 468 | goto co; 469 | s1: 470 | if (!il_tst("GO")) goto s3; 471 | if (!il_tst("TO")) goto s2; 472 | il_call(X2); goto expr; 473 | x2: errno = 0; 474 | il_done(); 475 | if (errno) goto error; 476 | errno = 0; 477 | il_xfer(); 478 | if (errno) goto error; 479 | goto stmt; 480 | s2: 481 | errno = 0; 482 | if (!il_tst("SUB")) errno = SYNTAX_ERROR; //from s14 483 | if (errno) goto error; 484 | il_call(X3); goto expr; 485 | x3: errno = 0; 486 | il_done(); 487 | if (errno) goto error; 488 | errno = 0; 489 | il_sav(); 490 | if (errno) goto error; 491 | errno = 0; 492 | il_xfer(); 493 | if (errno) goto error; 494 | goto stmt; 495 | s3: 496 | if (!il_tst("PRINT"))goto s8; 497 | s4: 498 | if (!il_tst("\"")) goto s7; 499 | errno = 0; 500 | il_prs(); 501 | if (errno) goto error; 502 | s5: 503 | if (!il_tst(",")) goto s6; 504 | il_spc(); 505 | goto s4; 506 | s6: errno = 0; 507 | il_done(); 508 | if (errno) goto error; 509 | il_nline(); 510 | if (il_nxt()) goto stmt; 511 | goto co; 512 | s7: 513 | il_call(X4); goto expr; 514 | x4: 515 | il_prn(); 516 | goto s5; 517 | s8: 518 | if (!il_tst("IF")) goto s9; 519 | il_call(X5); goto expr; 520 | x5: il_call(X6); goto relop; 521 | x6: il_call(X7); goto expr; 522 | x7: 523 | sba: 524 | errno = 0; 525 | if (!il_tst("THEN")) errno = SYNTAX_ERROR; 526 | if (errno) goto error; 527 | if (il_cmpr()) goto skip1; //likely trouble spot 528 | if (il_nxt()) goto stmt; 529 | goto co; 530 | skip1: 531 | goto stmt; 532 | s9: 533 | if (!il_tst("INPUT"))goto s12; 534 | s10: 535 | errno = 0; 536 | il_tstv(); 537 | if (errno) goto error; 538 | il_innum(); 539 | il_store(); 540 | if (!il_tst(",")) goto s11; 541 | goto s10; 542 | s11: errno = 0; 543 | il_done(); 544 | if (errno) goto error; 545 | if(il_nxt()) goto stmt; 546 | goto co; 547 | s12: 548 | if (!il_tst("RETURN"))goto s13; 549 | errno = 0; 550 | il_done(); 551 | if (errno) goto error; 552 | errno = 0; 553 | il_rstr(); //another trouble spot 554 | if (errno) goto error; 555 | if(il_nxt()) goto stmt; 556 | goto co; 557 | s13: 558 | if (!il_tst("END")) goto s14; 559 | goto co; //fin 560 | s14: 561 | if (!il_tst("LIST")) goto s15; 562 | errno = 0; 563 | il_done(); 564 | if (errno) goto error; 565 | il_lst(); 566 | if (il_nxt()) goto stmt; 567 | goto co; 568 | s15: 569 | if (!il_tst("RUN")) goto s16; 570 | errno = 0; 571 | il_done(); 572 | if (errno) goto error; 573 | il_run(); 574 | errno = 0; 575 | il_xfer(); 576 | if (errno) goto error; 577 | goto stmt; 578 | s16: 579 | errno = 0; 580 | if (!il_tst("CLEAR")) errno = SYNTAX_ERROR; 581 | if (errno) goto error; 582 | errno = 0; 583 | il_done(); 584 | if (errno) goto error; 585 | goto start; 586 | s17: 587 | error: 588 | error(); 589 | goto co; 590 | expr: 591 | if (!il_tst("-")) goto e0; 592 | il_call(X9); goto term; 593 | x9: il_neg(); 594 | goto e1; 595 | e0: 596 | if (!il_tst("+")) goto e01; 597 | e01: il_call(X10); goto term; 598 | x10: 599 | e1: 600 | if (!il_tst("+")) goto e2; 601 | il_call(X11); goto term; 602 | x11: 603 | il_add(); 604 | goto e1; 605 | e2: 606 | if (!il_tst("-")) goto e3; 607 | il_call(X12); goto term; 608 | x12: 609 | il_sub(); 610 | goto e1; //changed from e3 611 | e3: 612 | t2: 613 | goto call_rtn; 614 | term: 615 | il_call(X13); goto fact; 616 | x13: 617 | t0: 618 | if (!il_tst("*")) goto t1; 619 | il_call(X14); goto fact; 620 | x14: 621 | il_mul(); 622 | goto t0; 623 | t1: 624 | if (!il_tst("/")) goto t2; //possible problem 625 | il_call(X15); goto fact; 626 | x15: 627 | il_div(); 628 | goto t0; 629 | fact: 630 | if (!il_tst("@(")) goto ab; 631 | il_call(X18); goto expr; 632 | x18: 633 | if (!il_tst(")")) goto f2; 634 | il_sze(); 635 | il_get(); 636 | goto call_rtn; 637 | ab: 638 | if (!il_tst("ABS(")) goto rn; 639 | il_call(X17); goto expr; 640 | x17: 641 | if (!il_tst(")")) goto f2; 642 | il_abs(); 643 | goto call_rtn; 644 | rn: 645 | if (!il_tst("RND(")) goto sz; 646 | il_call(X8); goto expr; 647 | x8: 648 | if (!il_tst(")")) goto f2; 649 | il_rnd(); 650 | goto call_rtn; 651 | sz: 652 | if (!il_tst("SIZE")) goto v1; 653 | il_sze(); 654 | goto call_rtn; 655 | v1: 656 | if (!il_tstv()) goto f0; 657 | il_ind(); 658 | goto call_rtn; 659 | f0: 660 | if (!il_tstn()) goto f1; 661 | goto call_rtn; 662 | f1: 663 | if (!il_tst("(")) goto f2; 664 | il_call(X16); goto expr; 665 | x16: 666 | if (!il_tst(")")) goto f2; 667 | goto call_rtn; 668 | f2: errno = SYNTAX_ERROR; 669 | goto error; 670 | relop: 671 | if (!il_tst("=")) goto r0; 672 | il_lit(0); 673 | goto call_rtn; 674 | r0: 675 | if (!il_tst("<")) goto r4; 676 | if (!il_tst("=")) goto r1; 677 | il_lit(2); 678 | goto call_rtn; 679 | r1: 680 | if (!il_tst(">")) goto r3; 681 | il_lit(3); 682 | goto call_rtn; 683 | r3: 684 | il_lit(1); 685 | goto call_rtn; 686 | r4: 687 | errno = 0; 688 | if (!il_tst(">")) errno = SYNTAX_ERROR; 689 | if (errno) goto error; 690 | if (!il_tst("=")) goto r5; 691 | il_lit(5); 692 | goto call_rtn; 693 | r5: 694 | if (!il_tst("<")) goto r6; 695 | il_lit(3); 696 | r6: 697 | il_lit(4); 698 | goto call_rtn; 699 | call_rtn: 700 | switch(ctrlstk[--ctrlstk_ptr]) { 701 | case X1: 702 | goto x1; 703 | case X2: 704 | goto x2; 705 | case X3: 706 | goto x3; 707 | case X4: 708 | goto x4; 709 | case X5: 710 | goto x5; 711 | case X6: 712 | goto x6; 713 | case X7: 714 | goto x7; 715 | case X8: 716 | goto x8; 717 | case X9: 718 | goto x9; 719 | case X10: 720 | goto x10; 721 | case X11: 722 | goto x11; 723 | case X12: 724 | goto x12; 725 | case X13: 726 | goto x13; 727 | case X14: 728 | goto x14; 729 | case X15: 730 | goto x15; 731 | case X16: 732 | goto x16; 733 | case X17: 734 | goto x17; 735 | case X18: 736 | goto x18; 737 | case X19: 738 | goto x19; 739 | case X20: 740 | goto x20; 741 | } 742 | stop: 743 | #if CONSOLE == 1 744 | Serial.print("\n"); 745 | #endif 746 | goto co; 747 | } 748 | -------------------------------------------------------------------------------- /develop/config.ino: -------------------------------------------------------------------------------- 1 | #ifndef CONSOLE 2 | #define CONSOLE 1 3 | #endif 4 | 5 | #ifndef PHONE 6 | #define PHONE 1 7 | #endif 8 | 9 | #ifndef RAM 10 | #define RAM 0 11 | #endif 12 | 13 | #ifndef FLASH 14 | #define FLASH 1 15 | #endif 16 | 17 | #ifndef CARD 18 | #define CARD 0 19 | #endif 20 | 21 | #ifndef WIDTH 22 | #define WIDTH 64 23 | #endif 24 | 25 | #ifndef SIZE 26 | #define SIZE 514 27 | #endif 28 | 29 | #ifndef BLOCKSIZE 30 | #define BLOCKSIZE 512 31 | #endif 32 | 33 | #ifndef STACKSIZE 34 | #define STACKSIZE 16 35 | #endif 36 | 37 | #ifndef MAX_POS 38 | #define MAX_POS 32767 39 | #endif 40 | 41 | #ifndef MAX_NEG 42 | #define MAX_NEG -32767 43 | #endif 44 | 45 | #ifndef X1 46 | #define X1 0 47 | #endif 48 | 49 | #ifndef X2 50 | #define X2 1 51 | #endif 52 | 53 | #ifndef X3 54 | #define X3 2 55 | #endif 56 | 57 | #ifndef X4 58 | #define X4 3 59 | #endif 60 | 61 | #ifndef X5 62 | #define X5 4 63 | #endif 64 | 65 | #ifndef X6 66 | #define X6 5 67 | #endif 68 | 69 | #ifndef X7 70 | #define X7 6 71 | #endif 72 | 73 | #ifndef X8 74 | #define X8 7 75 | #endif 76 | 77 | #ifndef X9 78 | #define X9 8 79 | #endif 80 | 81 | #ifndef X10 82 | #define X10 9 83 | #endif 84 | 85 | #ifndef X11 86 | #define X11 10 87 | #endif 88 | 89 | #ifndef X12 90 | #define X12 11 91 | #endif 92 | 93 | #ifndef X13 94 | #define X13 12 95 | #endif 96 | 97 | #ifndef X14 98 | #define X14 13 99 | #endif 100 | 101 | #ifndef X15 102 | #define X15 14 103 | #endif 104 | 105 | #ifndef X16 106 | #define X16 15 107 | #endif 108 | 109 | #ifndef X17 110 | #define X17 16 111 | #endif 112 | 113 | #ifndef X18 114 | #define X18 17 115 | #endif 116 | 117 | #ifndef X19 118 | #define X19 18 119 | #endif 120 | 121 | #ifndef X20 122 | #define X20 19 123 | #endif 124 | 125 | #ifndef X21 126 | #define X21 20 127 | #endif 128 | 129 | #ifndef X22 130 | #define X22 21 131 | #endif 132 | 133 | #ifndef SYNTAX_ERROR 134 | #define SYNTAX_ERROR 1 135 | #endif 136 | 137 | #ifndef MISSING_LINE 138 | #define MISSING_LINE 2 139 | #endif 140 | 141 | #ifndef LINE_NUMBER_TOO_LARGE 142 | #define LINE_NUMBER_TOO_LARGE 3 143 | #endif 144 | 145 | #ifndef TOO_MANY_GOSUBS 146 | #define TOO_MANY_GOSUBS 4 147 | #endif 148 | 149 | #ifndef RETURN_WITHOUT_GOSUB 150 | #define RETURN_WITHOUT_GOSUB 5 151 | #endif 152 | 153 | #ifndef EXPRESSION_TOO_COMPLEX 154 | #define EXPRESSION_TOO_COMPLEX 6 155 | #endif 156 | 157 | #ifndef TOO_MANY_LINES 158 | #define TOO_MANY_LINES 7 159 | #endif 160 | 161 | #ifndef DIVISION_BY_ZERO 162 | #define DIVISION_BY_ZERO 8 163 | #endif 164 | -------------------------------------------------------------------------------- /develop/develop.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | prelude(); 3 | } 4 | 5 | void loop() { 6 | repl(); 7 | } 8 | -------------------------------------------------------------------------------- /develop/lib.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const PROGMEM float coeffs[] = {1.76384252869671, 1.7154572200005442, 1.6351696263031674, 1.5766928552532127, 5 | 1.3063456859075537, 1.191398608984867, 0.9857963844595683, 0.8104826280099796}; 6 | const PROGMEM float black[] = { 7 | 0.006878018379211426, 0.006935006483945974, 0.007106103713363648, 0.007391708330140939, 0.007792482496781619, 8 | 0.00830934986709432, 0.00894349222307339, 0.009696345165972634, 0.01056959287283113, 0.011565161932160159, 9 | 0.01268521427490911, 0.013932139219203735, 0.015308544649676376, 0.016817247354482902, 0.018461262545322876, 10 | 0.020243792587934212, 0.02216821497262504, 0.024238069556421507, 0.02645704511035033, 0.0288289652072306, 11 | 0.03135777348712121, 0.03404751833924685, 0.036902337040809766, 0.0399264393945777, 0.043124090908518736, 12 | 0.04649959556202746, 0.050057278204451744, 0.05380146663268032, 0.05773647339548663, 0.06186657737314577, 13 | 0.06619600518153684, 0.07072891245052318, 0.07546936502685536, 0.08042132015217372, 0.0855886076668918, 14 | 0.09097491129082115, 0.09658375003135286, 0.10241845976983843, 0.10848217507651484, 0.11477781130389673, 15 | 0.12130804700801177, 0.128075306746186, 0.1350817442992961, 0.14232922636549503, 0.14981931677139196, 16 | 0.15755326124552416, 0.16553197279770526, 0.1737560177464731, 0.18222560243538719, 0.1909405606773603, 17 | 0.1999003419645327, 0.20910400047943747, 0.21855018494134748, 0.2282371293197531, 0.2381626444448992, 18 | 0.24832411054320663, 0.25871847072323495, 0.2693422254356059, 0.28019142792800555, 0.29126168071403125, 19 | 0.3025481330722449, 0.31404547958934503, 0.3257479597588838, 0.3376493586444366, 0.34974300861358637, 20 | 0.36202179214651986, 0.3744781457204527, 0.38710406476851533, 0.3998911097091411, 0.41283041303941553, 21 | 0.4259126874832729, 0.43912823518286914, 0.45246695791893, 0.46591836834336936, 0.4794716022050044, 22 | 0.49311543154676896, 0.5068382788504501, 0.5206282321026424, 0.5344730607533511, 0.5483602325364739, 23 | 0.5622769311192501, 0.5762100745457207, 0.5901463344372482, 0.6040721559112647, 0.6179737781776001, 24 | 0.6318372557700426, 0.6456484803691538, 0.6593932031708652, 0.6730570577539623, 0.6866255833982696, 25 | 0.7000842488041658, 0.7134184761629803, 0.7266136655268723, 0.7396552194259599, 0.7525285676797484, 26 | 0.7652191923493276, 0.7777126527763367, 0.7899946106543597, 0.8020508550782071, 0.8138673275164574, 27 | 0.8254301466526721, 0.8367256330408851, 0.8477403335212518, 0.8584610453421903, 0.8688748399358914, 28 | 0.8789690862947551, 0.8887314738971245, 0.8981500351315997, 0.9072131671702709, 0.9159096532423648, 29 | 0.9242286832610802, 0.9321598737577689, 0.9396932870791218, 0.9468194498046159, 0.9535293703431773, 30 | 0.9598145556698215, 0.9656670271649104, 0.9710793355206584, 0.9760445746815715, 0.9805563947876479, 31 | 0.9846090140913881, 0.9881972298219366, 0.9913164279720323, 0.9939625919858431, 0.9961323103282166, 32 | 0.9978227829183829, 0.999031826413684, 0.9997578783314818, 1.0, 0.9997578783314818, 33 | 0.999031826413684, 0.9978227829183829, 0.9961323103282167, 0.9939625919858431, 0.9913164279720325, 34 | 0.9881972298219366, 0.9846090140913881, 0.9805563947876479, 0.9760445746815715, 0.9710793355206585, 35 | 0.9656670271649104, 0.9598145556698215, 0.9535293703431773, 0.9468194498046159, 0.9396932870791218, 36 | 0.9321598737577689, 0.9242286832610804, 0.9159096532423648, 0.9072131671702709, 0.8981500351315997, 37 | 0.8887314738971245, 0.8789690862947551, 0.8688748399358914, 0.8584610453421905, 0.8477403335212519, 38 | 0.8367256330408852, 0.8254301466526722, 0.8138673275164574, 0.8020508550782071, 0.7899946106543597, 39 | 0.7777126527763368, 0.7652191923493278, 0.7525285676797486, 0.7396552194259604, 0.7266136655268729, 40 | 0.7134184761629807, 0.7000842488041658, 0.6866255833982696, 0.6730570577539624, 0.6593932031708655, 41 | 0.6456484803691539, 0.6318372557700427, 0.6179737781776002, 0.6040721559112648, 0.5901463344372486, 42 | 0.5762100745457212, 0.5622769311192506, 0.5483602325364738, 0.5344730607533511, 0.5206282321026424, 43 | 0.5068382788504502, 0.49311543154676907, 0.4794716022050045, 0.46591836834336964, 0.4524669579189302, 44 | 0.43912823518286936, 0.42591268748327327, 0.41283041303941537, 0.399891109709141, 0.38710406476851533, 45 | 0.3744781457204527, 0.36202179214651997, 0.34974300861358654, 0.3376493586444368, 0.32574795975888404, 46 | 0.31404547958934526, 0.30254813307224515, 0.2912616807140315, 0.2801914279280055, 0.26934222543560593, 47 | 0.25871847072323495, 0.24832411054320663, 0.23816264444489932, 0.22823712931975318, 0.21855018494134754, 48 | 0.20910400047943767, 0.19990034196453288, 0.1909405606773605, 0.1822256024353871, 0.173756017746473, 49 | 0.16553197279770523, 0.15755326124552416, 0.14981931677139204, 0.1423292263654951, 0.13508174429929623, 50 | 0.12807530674618617, 0.12130804700801193, 0.11477781130389693, 0.10848217507651507, 0.10241845976983847, 51 | 0.09658375003135287, 0.0909749112908212, 0.08558860766689186, 0.08042132015217375, 0.07546936502685539, 52 | 0.07072891245052329, 0.066196005181537, 0.06186657737314586, 0.057736473395486716, 0.05380146663268044, 53 | 0.050057278204451716, 0.04649959556202747, 0.04312409090851873, 0.03992643939457768, 0.036902337040809786, 54 | 0.03404751833924687, 0.03135777348712121, 0.028828965207230647, 0.02645704511035038, 0.02423806955642155, 55 | 0.022168214972625076, 0.02024379258793422, 0.018461262545322883, 0.016817247354482902, 0.015308544649676362, 56 | 0.013932139219203707, 0.012685214274909082, 0.011565161932160187, 0.010569592872831171, 0.009696345165972661, 57 | 0.008943492223073418, 0.008309349867094334, 0.007792482496781619, 0.007391708330140939, 0.0071061037133636346, 58 | 0.006935006483945974}; 59 | 60 | Sd2Card card; 61 | 62 | volatile uint8_t sample; 63 | volatile byte subTick; 64 | volatile uint16_t playHead; 65 | volatile uint32_t block; 66 | volatile int blocks; 67 | 68 | int hook = 0; 69 | 70 | void lib_setup() { 71 | TCCR2A = 0b00000001; 72 | TCCR2B = 0b00000100; 73 | TIMSK2 = 0b00000000; 74 | OCR2B = 0; 75 | 76 | pinMode(2,OUTPUT); 77 | pinMode(3,OUTPUT); 78 | pinMode(A0,INPUT); 79 | 80 | delay(3000); 81 | 82 | if(!card.init(SPI_HALF_SPEED, 10)) { 83 | byte state = HIGH; 84 | for (byte i = 0; i < 6; i++) { 85 | digitalWrite(2,state); 86 | if (state == HIGH) { state = LOW; } else { state = HIGH; }; 87 | delay(250); 88 | } 89 | } 90 | card.partialBlockRead(1); 91 | 92 | //calibrate on hook voltage 93 | digitalWrite(2,LOW); 94 | delay(1000); 95 | hook = analogRead(A0); 96 | hook = 0.9*hook; 97 | digitalWrite(2,HIGH); 98 | #if PHONE == 1 99 | while(analogRead(A0) > hook) {}; 100 | #endif 101 | digitalWrite(2,LOW); 102 | } 103 | 104 | int dtmf() { 105 | int cur, num, r, c, buf[256]; 106 | float mass, q0[8], q1[8], q2[8]; 107 | byte last; 108 | 109 | #if CONSOLE == 1 110 | char keys[4][4] = { 111 | {'1','2','3','A'}, 112 | {'4','5','6','B'}, 113 | {'7','8','9','C'}, 114 | {'*','0','#','D'} 115 | }; 116 | #endif 117 | 118 | int nums[4][4] = { 119 | { 1, 2, 3,10}, 120 | { 4, 5, 6,11}, 121 | { 7, 8, 9,12}, 122 | {14, 0,15,13} 123 | }; 124 | 125 | num = 0; 126 | last = 0; 127 | while(1) { 128 | //bail if receiver is on the hook 129 | #if PHONE == 1 130 | if (analogRead(A0) > hook) { 131 | digitalWrite(2,HIGH); 132 | while(analogRead(A0) > hook) {}; 133 | digitalWrite(2,LOW); 134 | return -1; 135 | } 136 | #else 137 | return -1; 138 | #endif 139 | 140 | // ~8887Hz 141 | for (int i = 0; i < 256; i++) { 142 | buf[i] = analogRead(A0); 143 | } 144 | 145 | memset(q0,0,8*sizeof(float)); 146 | memset(q1,0,8*sizeof(float)); 147 | memset(q2,0,8*sizeof(float)); 148 | 149 | for (int n = 0; n < 256; n++) { 150 | float s = buf[n] * pgm_read_float_near(black + n); 151 | 152 | for (byte i = 0; i < 8; i++) { 153 | q0[i] = pgm_read_float_near(coeffs + i)*q1[i]-q2[i]+s; 154 | q2[i] = q1[i]; 155 | q1[i] = q0[i]; 156 | } 157 | 158 | for (byte i = 0; i < 8; i++) { 159 | q0[i] = sqrt(q1[i]*q1[i]+q2[i]*q2[i]-q1[i]*q2[i]*pgm_read_float_near(coeffs + i)); 160 | } 161 | } 162 | 163 | mass = 0; 164 | for (byte j = 0; j < 8; j++) mass = mass + q0[j]; 165 | 166 | r = -1; 167 | c = -1; 168 | for (byte i = 0; i < 8; i++) { 169 | if (q0[i]/mass > 0.3) { 170 | if (i < 4) { 171 | r = i; 172 | } else { 173 | c = i - 4; 174 | } 175 | } 176 | } 177 | 178 | if (r != -1 && c != -1) { 179 | digitalWrite(2,HIGH); 180 | 181 | if (last == 0) { 182 | last = 1; 183 | cur = nums[r][c]; 184 | switch(cur) { 185 | case 15: 186 | last = 15; 187 | break; 188 | case 14: 189 | num = 0; 190 | break; 191 | default: 192 | num = num * 10; 193 | num = num + cur; 194 | } 195 | } 196 | 197 | #if CONSOLE == 1 198 | Serial.print(keys[r][c]); 199 | #endif 200 | } else { 201 | digitalWrite(2,LOW); 202 | 203 | if (last == 15) { 204 | #if CONSOLE == 1 205 | Serial.print("\n"); 206 | #endif 207 | return num; 208 | } 209 | last = 0; 210 | 211 | #if CONSOLE == 1 212 | Serial.print("."); 213 | #endif 214 | } 215 | 216 | } 217 | 218 | } 219 | 220 | int play(int superblock, int blks) { 221 | block = superblock*8; 222 | blocks = blks; 223 | subTick = 0; 224 | playHead = 0; 225 | OCR2B = 0; 226 | TCCR2A = 0b00100011; 227 | TCCR2B = 0b00000001; 228 | TIMSK2 = 0b00000001; 229 | while(blocks > 0) { 230 | if (analogRead(A0) > hook) { 231 | TCCR2A = 0b00000001; 232 | TCCR2B = 0b00000100; 233 | TIMSK2 = 0b00000000; 234 | OCR2B = 0; 235 | digitalWrite(2,HIGH); 236 | while(analogRead(A0) > hook) {}; 237 | digitalWrite(2,LOW); 238 | return -1; 239 | } 240 | } 241 | TCCR2A = 0b00000001; 242 | TCCR2B = 0b00000100; 243 | TIMSK2 = 0b00000000; 244 | OCR2B = 0; 245 | return 1; 246 | } 247 | 248 | 249 | ISR(TIMER2_OVF_vect){ 250 | if (blocks < 0) { 251 | OCR2B = 0; 252 | return; 253 | } 254 | OCR2B = sample; 255 | if (subTick++ < 7) return; 256 | subTick = 0; 257 | card.readData(block, playHead, 1, (uint8_t*) &sample); 258 | if (playHead++ < BLOCKSIZE) return; 259 | playHead = 0; 260 | block++; 261 | blocks--; 262 | } 263 | -------------------------------------------------------------------------------- /develop/program.ino: -------------------------------------------------------------------------------- 1 | const PROGMEM int list[] = {10}; 2 | const PROGMEM char bas[][WIDTH] = { 3 | {"10 PRINT \"HELLO WORLD\"\n"}, 4 | }; 5 | -------------------------------------------------------------------------------- /develop/tny.ino: -------------------------------------------------------------------------------- 1 | int cur; 2 | int line_number; 3 | byte errno; 4 | 5 | void error() { 6 | #if CONSOLE == 1 7 | switch(errno) { 8 | case SYNTAX_ERROR: 9 | Serial.print(F("SYNTAX ERROR")); 10 | break; 11 | case MISSING_LINE: 12 | Serial.print(F("MISSING LINE")); 13 | break; 14 | case LINE_NUMBER_TOO_LARGE: 15 | Serial.print(F("LINE NUMBER TOO LARGE")); 16 | break; 17 | case TOO_MANY_GOSUBS: 18 | Serial.print(F("TOO MANY GOSUBS")); 19 | break; 20 | case RETURN_WITHOUT_GOSUB: 21 | Serial.print(F("RETURN WITHOUT GOSUB")); 22 | break; 23 | case EXPRESSION_TOO_COMPLEX: 24 | Serial.print(F("EXPRESSION TOO COMPLEX")); 25 | break; 26 | case TOO_MANY_LINES: 27 | Serial.print(F("TOO MANY LINES")); 28 | break; 29 | case DIVISION_BY_ZERO: 30 | Serial.print(F("DIVISION BY ZERO")); 31 | break; 32 | } 33 | Serial.print(F(": LINE: ")); 34 | Serial.print(line_number); 35 | Serial.print(F(" COL: ")); 36 | Serial.print(cur); 37 | Serial.print("\n"); 38 | #endif 39 | } 40 | 41 | int aestk[STACKSIZE]; 42 | byte aestk_ptr; 43 | 44 | int ctrlstk[STACKSIZE]; 45 | byte ctrlstk_ptr; 46 | 47 | int sbrstk[STACKSIZE]; 48 | byte sbrstk_ptr; 49 | 50 | char pgm[SIZE]; 51 | char lbuf[WIDTH]; 52 | 53 | int vars[26]; 54 | 55 | void il_init() { 56 | memset(pgm,'\n',SIZE); 57 | memset(vars,0,sizeof(int)*26); 58 | randomSeed(millis()); 59 | cur = 0; 60 | } 61 | 62 | void il_nline() { 63 | #if CONSOLE == 1 64 | Serial.print("\n"); 65 | #endif 66 | } 67 | 68 | byte getc() { 69 | #if CONSOLE == 1 70 | int data = Serial.read(); 71 | while (data == -1) data = Serial.read(); 72 | return data; 73 | #endif 74 | return 0; 75 | } 76 | 77 | int il_getline() { 78 | #if CONSOLE == 1 79 | cur = 0; 80 | char chr; 81 | unsigned char i; 82 | start: 83 | Serial.print("> "); 84 | i = 0; 85 | cur = 0; 86 | while((chr = getc()) && 87 | chr != '\n' && 88 | i < WIDTH) { 89 | if (chr == EOF) return 0; 90 | if (chr > 96 && chr < 123) chr = chr - 32; 91 | lbuf[i++] = chr; 92 | } 93 | if (i < 1) goto start; 94 | if (i >= WIDTH) { 95 | errno = EXPRESSION_TOO_COMPLEX; 96 | return 1; 97 | } 98 | lbuf[i] = '\n'; 99 | #else 100 | lbuf[0] = 'R'; 101 | lbuf[1] = 'U'; 102 | lbuf[2] = 'N'; 103 | lbuf[3] = '\n'; 104 | return 1; 105 | #endif 106 | } 107 | 108 | int il_tstl() { 109 | while(lbuf[cur] == ' ') cur++; 110 | if (lbuf[cur] > 47 && lbuf[cur] < 58) return 1; 111 | return 0; 112 | } 113 | 114 | int read_number(int* cur, char* line) { 115 | int num = 0; 116 | while(line[*cur] > 47 && line[*cur] < 58) { 117 | num = num * 10 + line[*cur] - 48; 118 | (*cur)++; 119 | } 120 | return num; 121 | } 122 | 123 | int load_nearest_line(int num) { 124 | #if RAM == 1 125 | int start; 126 | int end; 127 | int oldln = find_ram_line(num,&start,&end); 128 | if (oldln < 1) return 0; 129 | memcpy(lbuf,pgm+start,end-start+1); 130 | cur = 0; 131 | return read_number(&cur,lbuf); 132 | #endif 133 | #if FLASH == 1 134 | for (int i = 0; i < sizeof(list)/2; i++) { 135 | int line = pgm_read_word(list+i); 136 | if (line < num) continue; 137 | for (int j = 0; j < WIDTH; j++) { 138 | lbuf[j] = pgm_read_byte_near(bas[i]+j); 139 | if (pgm_read_byte_near(bas[i]+j) == '\n') break; 140 | } 141 | cur = 0; 142 | return read_number(&cur,lbuf); 143 | } 144 | return 0; 145 | #endif 146 | #if CARD == 1 147 | int line; 148 | for (unsigned int i = 0; i < MAX_POS ; i++) { 149 | card.readData(((i*2)/512),(i % 256)*2,2,(uint8_t*) &line); 150 | if (line < num) continue; 151 | card.readData(128+((i*64)/512),(i % 8)*64,64,(uint8_t*) lbuf); 152 | card.readEnd(); 153 | cur = 0; 154 | return read_number(&cur,lbuf); 155 | } 156 | card.readEnd(); 157 | return 0; 158 | #endif 159 | } 160 | 161 | int find_ram_line(int newln, int* start, int* end) { 162 | *start = 0; 163 | *end = 0; 164 | int oldln = -1; 165 | while(*end < SIZE) { 166 | if (pgm[*end] == '\n') { 167 | int cur = *start; 168 | oldln = read_number(&cur,pgm); 169 | if (oldln >= newln || oldln == 0) break; 170 | *start = *end+1; 171 | } 172 | (*end)++; 173 | } 174 | return oldln; 175 | } 176 | 177 | void il_insrt() { 178 | if (!RAM) return; 179 | int newln = read_number(&cur,lbuf); 180 | int start; 181 | int end; 182 | int oldln = find_ram_line(newln,&start,&end); 183 | if (oldln == newln) { 184 | memcpy(pgm+start,pgm+end+1,SIZE-(end+1)); 185 | } 186 | if (oldln >= newln && lbuf[cur] != '\n') { 187 | int mcur = cur; 188 | while (lbuf[mcur] != '\n') mcur++; 189 | memmove(pgm+start+mcur+1,pgm+start,SIZE-(start+mcur+1)); 190 | } 191 | if (lbuf[cur] != '\n') { 192 | while (lbuf[cur] != '\n') cur++; 193 | memcpy(pgm+start,lbuf,cur+1); 194 | } 195 | } 196 | 197 | void il_xinit() { 198 | aestk_ptr = 0; 199 | ctrlstk_ptr = 0; 200 | sbrstk_ptr = 0; 201 | line_number = 0; 202 | } 203 | 204 | int il_tst(const char* str) { 205 | int acur = cur; 206 | int bcur = 0; 207 | while(lbuf[acur] == ' ') acur++; 208 | while(str[bcur] == lbuf[acur]) { 209 | bcur++; 210 | acur++; 211 | }; 212 | if (str[bcur] != 0) return 0; 213 | cur = acur; 214 | return 1; 215 | } 216 | 217 | int il_tstv() { 218 | if (aestk_ptr == STACKSIZE) { 219 | errno = EXPRESSION_TOO_COMPLEX; 220 | return 0; 221 | } 222 | while(lbuf[cur] == ' ') cur++; 223 | if (lbuf[cur] < 65 || lbuf[cur] > 90) { 224 | errno = SYNTAX_ERROR; 225 | return 0; 226 | } 227 | aestk[aestk_ptr++] = lbuf[cur]-65; 228 | cur++; 229 | return 1; 230 | } 231 | 232 | void il_call(int lbl) { 233 | ctrlstk[ctrlstk_ptr++] = lbl; 234 | } 235 | 236 | void il_done() { 237 | while(lbuf[cur] == ' ') cur++; 238 | if (lbuf[cur] != '\n') errno = SYNTAX_ERROR; 239 | } 240 | 241 | void il_store() { 242 | int val = aestk[--aestk_ptr]; 243 | int idx = aestk[--aestk_ptr]; 244 | vars[idx] = val; 245 | } 246 | 247 | int il_nxt() { 248 | if (line_number == 0) return 0; 249 | line_number = load_nearest_line(line_number+1); 250 | if (line_number == 0) return 0; 251 | return 1; 252 | } 253 | 254 | void il_xfer() { 255 | line_number = aestk[--aestk_ptr]; 256 | line_number = load_nearest_line(line_number); 257 | } 258 | 259 | void il_sav() { 260 | sbrstk[sbrstk_ptr++] = line_number; 261 | } 262 | 263 | void il_prs() { 264 | #if CONSOLE == 1 265 | while(lbuf[cur] != '"') { 266 | if (lbuf[cur] == '\n') { 267 | errno = SYNTAX_ERROR; 268 | return; 269 | } 270 | Serial.print(lbuf[cur]); 271 | cur++; 272 | } 273 | cur++; 274 | #endif 275 | } 276 | 277 | void il_spc() { 278 | #if CONSOLE == 1 279 | Serial.print(" "); 280 | #endif 281 | } 282 | 283 | void il_prn() { 284 | #if CONSOLE == 1 285 | Serial.print(aestk[--aestk_ptr]); 286 | #else 287 | aestk[--aestk_ptr]; 288 | #endif 289 | } 290 | 291 | int il_cmpr() { 292 | int b = aestk[--aestk_ptr]; 293 | int rel = aestk[--aestk_ptr]; 294 | int a = aestk[--aestk_ptr]; 295 | switch(rel) { 296 | case 0: //= 297 | if (a == b) return 1; 298 | break; 299 | case 1: //< 300 | if (a < b) return 1; 301 | break; 302 | case 2: //<= 303 | if (a <= b) return 1; 304 | break; 305 | case 3: //<> 306 | if (a != b) return 1; 307 | break; 308 | case 4: //> 309 | if (a > b) return 1; 310 | break; 311 | case 5: //>= 312 | if (a >= b) return 1; 313 | break; 314 | } 315 | return 0; 316 | } 317 | 318 | void il_innum() { 319 | int num = 0; 320 | char chr; 321 | while((chr = getc()) && chr > 47 && chr < 58) { 322 | num = num * 10 + chr - 48; 323 | } 324 | aestk[aestk_ptr++] = num; 325 | } 326 | 327 | void il_dtmf() { 328 | aestk[aestk_ptr++] = dtmf(); 329 | } 330 | 331 | void il_rstr() { 332 | if (sbrstk_ptr == 0) { 333 | errno = RETURN_WITHOUT_GOSUB; 334 | return; 335 | } 336 | line_number = sbrstk[--sbrstk_ptr]; 337 | } 338 | 339 | void il_lst() { 340 | #if CONSOLE == 1 341 | int line = load_nearest_line(0); 342 | while (line != 0) { 343 | for (int i = 0; i < WIDTH ; i++) { 344 | char chr = lbuf[i]; 345 | if (chr == '\n') break; 346 | Serial.print(chr); 347 | } 348 | Serial.print("\n"); 349 | line = load_nearest_line(line+1); 350 | } 351 | #endif 352 | } 353 | 354 | void il_run() { 355 | aestk[aestk_ptr++] = load_nearest_line(0); 356 | } 357 | 358 | void il_neg() { 359 | aestk[aestk_ptr-1] = -1*aestk[aestk_ptr-1]; 360 | } 361 | 362 | void il_add() { 363 | int b = aestk[--aestk_ptr]; 364 | int a = aestk[--aestk_ptr]; 365 | aestk[aestk_ptr++] = a+b; 366 | } 367 | 368 | void il_sub() { 369 | int b = aestk[--aestk_ptr]; 370 | int a = aestk[--aestk_ptr]; 371 | aestk[aestk_ptr++] = a-b; 372 | } 373 | 374 | void il_mul() { 375 | int b = aestk[--aestk_ptr]; 376 | int a = aestk[--aestk_ptr]; 377 | aestk[aestk_ptr++] = a*b; 378 | } 379 | 380 | void il_div() { 381 | int b = aestk[--aestk_ptr]; 382 | int a = aestk[--aestk_ptr]; 383 | aestk[aestk_ptr++] = a/b; 384 | } 385 | 386 | void il_ind() { 387 | int i = aestk[--aestk_ptr]; 388 | aestk[aestk_ptr++] = vars[i]; 389 | } 390 | 391 | int il_tstn() { 392 | if (lbuf[cur] < 48 || lbuf[cur] > 57) return 0; 393 | aestk[aestk_ptr++] = read_number(&cur,lbuf); 394 | return 1; 395 | } 396 | 397 | void il_lit(int val) { 398 | aestk[aestk_ptr++] = val; 399 | } 400 | 401 | void il_sze() { 402 | int start; 403 | int end; 404 | find_ram_line(MAX_POS,&start,&end); 405 | aestk[aestk_ptr++] = SIZE-(end+2); //newline terminates program 406 | } 407 | 408 | void il_rnd() { 409 | aestk[aestk_ptr++] = random(1,aestk[--aestk_ptr]+1); 410 | } 411 | 412 | void il_abs() { 413 | int a = aestk[--aestk_ptr]; 414 | aestk[aestk_ptr++] = abs(a); 415 | } 416 | 417 | void il_ply() { 418 | int b = aestk[--aestk_ptr]; 419 | int a = aestk[--aestk_ptr]; 420 | #if CONSOLE == 1 421 | Serial.print("playing: "); 422 | Serial.print(a); 423 | Serial.print(", "); 424 | Serial.print(b); 425 | Serial.print("\n"); 426 | #endif 427 | #if PHONE == 1 428 | aestk[aestk_ptr++] = play(a,b); 429 | #else 430 | aestk[aestk_ptr++] = -1; 431 | #endif 432 | } 433 | 434 | void il_get() { 435 | int size = aestk[--aestk_ptr]; 436 | int idx = aestk[--aestk_ptr]; 437 | aestk[aestk_ptr++] = ((int*) (pgm+SIZE-size))[idx]; 438 | } 439 | 440 | void il_set() { 441 | int size = aestk[--aestk_ptr]; 442 | int val = aestk[--aestk_ptr]; 443 | int idx = aestk[--aestk_ptr]; 444 | ((int*) (pgm+SIZE-size))[idx] = val; 445 | } 446 | 447 | void prelude() { 448 | lib_setup(); 449 | 450 | #if CONSOLE == 1 451 | Serial.begin(9600); 452 | while (!Serial) {}; 453 | Serial.println(F("TINY BASIC FOR ARDUINO")); 454 | Serial.println(F("BY DENNIS ALLISON")); 455 | Serial.println(F("MODIFIED AND TRANSLATED BY TREVOR JAY")); 456 | Serial.println(F("2020")); 457 | Serial.println(F("@COPYLEFT")); 458 | Serial.println(F("ALL WRONGS RESERVED")); 459 | #endif 460 | } 461 | 462 | void repl() { 463 | start: il_init(); 464 | il_nline(); //errent? 465 | co: errno = 0; 466 | if(!il_getline()) goto stop; 467 | if (errno) goto error; 468 | if (!il_tstl()) goto xec; 469 | il_insrt(); 470 | goto co; 471 | xec: il_xinit(); 472 | stmt: 473 | if (!il_tst("LET")) goto s1; 474 | if (!il_tst("@(")) goto l1; 475 | il_call(X19); goto expr; 476 | x19: 477 | errno = 0; 478 | if (!il_tst(")")) errno = SYNTAX_ERROR; 479 | if (errno) goto error; 480 | errno = 0; 481 | if (!il_tst("=")) errno = SYNTAX_ERROR; 482 | if (errno) goto error; 483 | il_call(X20); goto expr; 484 | x20: errno = 0; 485 | il_done(); 486 | if (errno) goto error; 487 | il_sze(); 488 | il_set(); 489 | goto l2; 490 | l1: errno = 0; 491 | il_tstv(); 492 | if (errno) goto error; 493 | errno = 0; 494 | if (!il_tst("=")) errno = SYNTAX_ERROR; 495 | if (errno) goto error; 496 | il_call(X1); goto expr; 497 | x1: errno = 0; 498 | il_done(); 499 | if (errno) goto error; 500 | il_store(); 501 | l2: 502 | if (il_nxt()) goto stmt; 503 | goto co; 504 | s1: 505 | if (!il_tst("GO")) goto s3; 506 | if (!il_tst("TO")) goto s2; 507 | il_call(X2); goto expr; 508 | x2: errno = 0; 509 | il_done(); 510 | if (errno) goto error; 511 | errno = 0; 512 | il_xfer(); 513 | if (errno) goto error; 514 | goto stmt; 515 | s2: 516 | errno = 0; 517 | if (!il_tst("SUB")) errno = SYNTAX_ERROR; //from s14 518 | if (errno) goto error; 519 | il_call(X3); goto expr; 520 | x3: errno = 0; 521 | il_done(); 522 | if (errno) goto error; 523 | errno = 0; 524 | il_sav(); 525 | if (errno) goto error; 526 | errno = 0; 527 | il_xfer(); 528 | if (errno) goto error; 529 | goto stmt; 530 | s3: 531 | if (!il_tst("PRINT"))goto s8; 532 | s4: 533 | if (!il_tst("\"")) goto s7; 534 | errno = 0; 535 | il_prs(); 536 | if (errno) goto error; 537 | s5: 538 | if (!il_tst(",")) goto s6; 539 | il_spc(); 540 | goto s4; 541 | s6: errno = 0; 542 | il_done(); 543 | if (errno) goto error; 544 | il_nline(); 545 | if (il_nxt()) goto stmt; 546 | goto co; 547 | s7: 548 | il_call(X4); goto expr; 549 | x4: 550 | il_prn(); 551 | goto s5; 552 | s8: 553 | if (!il_tst("IF")) goto s9; 554 | il_call(X5); goto expr; 555 | x5: il_call(X6); goto relop; 556 | x6: il_call(X7); goto expr; 557 | x7: 558 | sba: 559 | errno = 0; 560 | if (!il_tst("THEN")) errno = SYNTAX_ERROR; 561 | if (errno) goto error; 562 | if (il_cmpr()) goto skip1; //likely trouble spot 563 | if (il_nxt()) goto stmt; 564 | goto co; 565 | skip1: 566 | goto stmt; 567 | s9: 568 | if (!il_tst("INPUT"))goto dt; 569 | s10: 570 | errno = 0; 571 | il_tstv(); 572 | if (errno) goto error; 573 | il_innum(); 574 | il_store(); 575 | if (!il_tst(",")) goto s11; 576 | goto s10; 577 | s11: errno = 0; 578 | il_done(); 579 | if (errno) goto error; 580 | if(il_nxt()) goto stmt; 581 | goto co; 582 | dt: 583 | if (!il_tst("DTMF")) goto s12; 584 | dtl: 585 | errno = 0; 586 | il_tstv(); 587 | if (errno) goto error; 588 | il_dtmf(); 589 | il_store(); 590 | if (!il_tst(",")) goto dte; 591 | goto dtl; 592 | dte: errno = 0; 593 | il_done(); 594 | if (errno) goto error; 595 | if(il_nxt()) goto stmt; 596 | goto co; 597 | s12: 598 | if (!il_tst("RETURN"))goto s13; 599 | errno = 0; 600 | il_done(); 601 | if (errno) goto error; 602 | errno = 0; 603 | il_rstr(); //another trouble spot 604 | if (errno) goto error; 605 | if(il_nxt()) goto stmt; 606 | goto co; 607 | s13: 608 | if (!il_tst("END")) goto s14; 609 | goto co; //fin 610 | s14: 611 | if (!il_tst("LIST")) goto s15; 612 | errno = 0; 613 | il_done(); 614 | if (errno) goto error; 615 | il_lst(); 616 | if (il_nxt()) goto stmt; 617 | goto co; 618 | s15: 619 | if (!il_tst("RUN")) goto s16; 620 | errno = 0; 621 | il_done(); 622 | if (errno) goto error; 623 | il_run(); 624 | errno = 0; 625 | il_xfer(); 626 | if (errno) goto error; 627 | goto stmt; 628 | s16: 629 | errno = 0; 630 | if (!il_tst("CLEAR")) errno = SYNTAX_ERROR; 631 | if (errno) goto error; 632 | errno = 0; 633 | il_done(); 634 | if (errno) goto error; 635 | goto start; 636 | s17: 637 | error: 638 | error(); 639 | goto co; 640 | expr: 641 | if (!il_tst("-")) goto e0; 642 | il_call(X9); goto term; 643 | x9: il_neg(); 644 | goto e1; 645 | e0: 646 | if (!il_tst("+")) goto e01; 647 | e01: il_call(X10); goto term; 648 | x10: 649 | e1: 650 | if (!il_tst("+")) goto e2; 651 | il_call(X11); goto term; 652 | x11: 653 | il_add(); 654 | goto e1; 655 | e2: 656 | if (!il_tst("-")) goto e3; 657 | il_call(X12); goto term; 658 | x12: 659 | il_sub(); 660 | goto e1; //changed from e3 661 | e3: 662 | t2: 663 | goto call_rtn; 664 | term: 665 | il_call(X13); goto fact; 666 | x13: 667 | t0: 668 | if (!il_tst("*")) goto t1; 669 | il_call(X14); goto fact; 670 | x14: 671 | il_mul(); 672 | goto t0; 673 | t1: 674 | if (!il_tst("/")) goto t2; //possible problem 675 | il_call(X15); goto fact; 676 | x15: 677 | il_div(); 678 | goto t0; 679 | fact: 680 | if (!il_tst("@(")) goto ab; 681 | il_call(X18); goto expr; 682 | x18: 683 | if (!il_tst(")")) goto f2; 684 | il_sze(); 685 | il_get(); 686 | goto call_rtn; 687 | ab: 688 | if (!il_tst("ABS(")) goto pl; 689 | il_call(X17); goto expr; 690 | x17: 691 | if (!il_tst(")")) goto f2; 692 | il_abs(); 693 | goto call_rtn; 694 | pl: 695 | if (!il_tst("PLAY(")) goto rn; 696 | il_call(X21); goto expr; 697 | x21: 698 | if (!il_tst(",")) goto f2; 699 | il_call(X22); goto expr; 700 | x22: 701 | if (!il_tst(")")) goto f2; 702 | il_ply(); 703 | goto call_rtn; 704 | rn: 705 | if (!il_tst("RND(")) goto sz; 706 | il_call(X8); goto expr; 707 | x8: 708 | if (!il_tst(")")) goto f2; 709 | il_rnd(); 710 | goto call_rtn; 711 | sz: 712 | if (!il_tst("SIZE")) goto v1; 713 | il_sze(); 714 | goto call_rtn; 715 | v1: 716 | if (!il_tstv()) goto f0; 717 | il_ind(); 718 | goto call_rtn; 719 | f0: 720 | if (!il_tstn()) goto f1; 721 | goto call_rtn; 722 | f1: 723 | if (!il_tst("(")) goto f2; 724 | il_call(X16); goto expr; 725 | x16: 726 | if (!il_tst(")")) goto f2; 727 | goto call_rtn; 728 | f2: errno = SYNTAX_ERROR; 729 | goto error; 730 | relop: 731 | if (!il_tst("=")) goto r0; 732 | il_lit(0); 733 | goto call_rtn; 734 | r0: 735 | if (!il_tst("<")) goto r4; 736 | if (!il_tst("=")) goto r1; 737 | il_lit(2); 738 | goto call_rtn; 739 | r1: 740 | if (!il_tst(">")) goto r3; 741 | il_lit(3); 742 | goto call_rtn; 743 | r3: 744 | il_lit(1); 745 | goto call_rtn; 746 | r4: 747 | errno = 0; 748 | if (!il_tst(">")) errno = SYNTAX_ERROR; 749 | if (errno) goto error; 750 | if (!il_tst("=")) goto r5; 751 | il_lit(5); 752 | goto call_rtn; 753 | r5: 754 | if (!il_tst("<")) goto r6; 755 | il_lit(3); 756 | r6: 757 | il_lit(4); 758 | goto call_rtn; 759 | call_rtn: 760 | switch(ctrlstk[--ctrlstk_ptr]) { 761 | case X1: 762 | goto x1; 763 | case X2: 764 | goto x2; 765 | case X3: 766 | goto x3; 767 | case X4: 768 | goto x4; 769 | case X5: 770 | goto x5; 771 | case X6: 772 | goto x6; 773 | case X7: 774 | goto x7; 775 | case X8: 776 | goto x8; 777 | case X9: 778 | goto x9; 779 | case X10: 780 | goto x10; 781 | case X11: 782 | goto x11; 783 | case X12: 784 | goto x12; 785 | case X13: 786 | goto x13; 787 | case X14: 788 | goto x14; 789 | case X15: 790 | goto x15; 791 | case X16: 792 | goto x16; 793 | case X17: 794 | goto x17; 795 | case X18: 796 | goto x18; 797 | case X19: 798 | goto x19; 799 | case X20: 800 | goto x20; 801 | case X21: 802 | goto x21; 803 | case X22: 804 | goto x22; 805 | } 806 | stop: 807 | #if CONSOLE == 1 808 | Serial.print("\n"); 809 | #endif 810 | goto co; 811 | } 812 | --------------------------------------------------------------------------------