Tom Van den Bon
/
TinyBasicNucleo
A port of TinyBasic Plus (https://github.com/BleuLlama/TinyBasicPlus) to mbed (focus on Nucleo)
main.cpp@0:c52ead8719b3, 2015-01-21 (annotated)
- Committer:
- tomvdb
- Date:
- Wed Jan 21 15:32:36 2015 +0000
- Revision:
- 0:c52ead8719b3
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tomvdb | 0:c52ead8719b3 | 1 | /* |
tomvdb | 0:c52ead8719b3 | 2 | |
tomvdb | 0:c52ead8719b3 | 3 | A C implementation of Tiny Basic, with a focus on support for mbed/nucleo. This has been ported from TinyBasic Plus (https://github.com/BleuLlama/TinyBasicPlus) |
tomvdb | 0:c52ead8719b3 | 4 | |
tomvdb | 0:c52ead8719b3 | 5 | Nucleo Port by Tom Van den Bon |
tomvdb | 0:c52ead8719b3 | 6 | |
tomvdb | 0:c52ead8719b3 | 7 | */ |
tomvdb | 0:c52ead8719b3 | 8 | |
tomvdb | 0:c52ead8719b3 | 9 | #define kVersion "v0.1" |
tomvdb | 0:c52ead8719b3 | 10 | |
tomvdb | 0:c52ead8719b3 | 11 | /* |
tomvdb | 0:c52ead8719b3 | 12 | v0.1: 2015/01/21 |
tomvdb | 0:c52ead8719b3 | 13 | |
tomvdb | 0:c52ead8719b3 | 14 | Initial code from TinyBasic Plus ported to run on the Nucleo |
tomvdb | 0:c52ead8719b3 | 15 | |
tomvdb | 0:c52ead8719b3 | 16 | - filesystem, eeprom and sdcard not implemented yet |
tomvdb | 0:c52ead8719b3 | 17 | */ |
tomvdb | 0:c52ead8719b3 | 18 | |
tomvdb | 0:c52ead8719b3 | 19 | |
tomvdb | 0:c52ead8719b3 | 20 | |
tomvdb | 0:c52ead8719b3 | 21 | #include "mbed.h" |
tomvdb | 0:c52ead8719b3 | 22 | |
tomvdb | 0:c52ead8719b3 | 23 | Serial pc(SERIAL_TX, SERIAL_RX); |
tomvdb | 0:c52ead8719b3 | 24 | |
tomvdb | 0:c52ead8719b3 | 25 | #ifndef pgm_read_byte |
tomvdb | 0:c52ead8719b3 | 26 | #define pgm_read_byte( A ) *(A) |
tomvdb | 0:c52ead8719b3 | 27 | #endif |
tomvdb | 0:c52ead8719b3 | 28 | |
tomvdb | 0:c52ead8719b3 | 29 | #ifndef boolean |
tomvdb | 0:c52ead8719b3 | 30 | #define boolean int |
tomvdb | 0:c52ead8719b3 | 31 | #define true 1 |
tomvdb | 0:c52ead8719b3 | 32 | #define false 0 |
tomvdb | 0:c52ead8719b3 | 33 | #endif |
tomvdb | 0:c52ead8719b3 | 34 | |
tomvdb | 0:c52ead8719b3 | 35 | boolean inhibitOutput = false; |
tomvdb | 0:c52ead8719b3 | 36 | static boolean runAfterLoad = false; |
tomvdb | 0:c52ead8719b3 | 37 | static boolean triggerRun = false; |
tomvdb | 0:c52ead8719b3 | 38 | |
tomvdb | 0:c52ead8719b3 | 39 | // these will select, at runtime, where IO happens through for load/save |
tomvdb | 0:c52ead8719b3 | 40 | enum { |
tomvdb | 0:c52ead8719b3 | 41 | kStreamSerial = 0, |
tomvdb | 0:c52ead8719b3 | 42 | kStreamEEProm, |
tomvdb | 0:c52ead8719b3 | 43 | kStreamFile |
tomvdb | 0:c52ead8719b3 | 44 | }; |
tomvdb | 0:c52ead8719b3 | 45 | static unsigned char inStream = kStreamSerial; |
tomvdb | 0:c52ead8719b3 | 46 | static unsigned char outStream = kStreamSerial; |
tomvdb | 0:c52ead8719b3 | 47 | |
tomvdb | 0:c52ead8719b3 | 48 | // ASCII Characters |
tomvdb | 0:c52ead8719b3 | 49 | #define CR '\r' |
tomvdb | 0:c52ead8719b3 | 50 | #define NL '\n' |
tomvdb | 0:c52ead8719b3 | 51 | #define LF 0x0a |
tomvdb | 0:c52ead8719b3 | 52 | #define TAB '\t' |
tomvdb | 0:c52ead8719b3 | 53 | #define BELL '\b' |
tomvdb | 0:c52ead8719b3 | 54 | #define SPACE ' ' |
tomvdb | 0:c52ead8719b3 | 55 | #define SQUOTE '\'' |
tomvdb | 0:c52ead8719b3 | 56 | #define DQUOTE '\"' |
tomvdb | 0:c52ead8719b3 | 57 | #define CTRLC 0x03 |
tomvdb | 0:c52ead8719b3 | 58 | #define CTRLH 0x08 |
tomvdb | 0:c52ead8719b3 | 59 | #define CTRLS 0x13 |
tomvdb | 0:c52ead8719b3 | 60 | #define CTRLX 0x18 |
tomvdb | 0:c52ead8719b3 | 61 | |
tomvdb | 0:c52ead8719b3 | 62 | // size of our program ram |
tomvdb | 0:c52ead8719b3 | 63 | #define kRamSize 4096 /* arbitrary */ |
tomvdb | 0:c52ead8719b3 | 64 | |
tomvdb | 0:c52ead8719b3 | 65 | typedef short unsigned LINENUM; |
tomvdb | 0:c52ead8719b3 | 66 | |
tomvdb | 0:c52ead8719b3 | 67 | static unsigned char program[kRamSize]; |
tomvdb | 0:c52ead8719b3 | 68 | static const char * sentinel = "HELLO"; |
tomvdb | 0:c52ead8719b3 | 69 | static unsigned char *txtpos,*list_line; |
tomvdb | 0:c52ead8719b3 | 70 | static unsigned char expression_error; |
tomvdb | 0:c52ead8719b3 | 71 | static unsigned char *tempsp; |
tomvdb | 0:c52ead8719b3 | 72 | |
tomvdb | 0:c52ead8719b3 | 73 | // Keyword table and constants - the last character has 0x80 added to it |
tomvdb | 0:c52ead8719b3 | 74 | static unsigned char keywords[] = { |
tomvdb | 0:c52ead8719b3 | 75 | 'L','I','S','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 76 | 'L','O','A','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 77 | 'N','E','W'+0x80, |
tomvdb | 0:c52ead8719b3 | 78 | 'R','U','N'+0x80, |
tomvdb | 0:c52ead8719b3 | 79 | 'S','A','V','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 80 | 'N','E','X','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 81 | 'L','E','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 82 | 'I','F'+0x80, |
tomvdb | 0:c52ead8719b3 | 83 | 'G','O','T','O'+0x80, |
tomvdb | 0:c52ead8719b3 | 84 | 'G','O','S','U','B'+0x80, |
tomvdb | 0:c52ead8719b3 | 85 | 'R','E','T','U','R','N'+0x80, |
tomvdb | 0:c52ead8719b3 | 86 | 'R','E','M'+0x80, |
tomvdb | 0:c52ead8719b3 | 87 | 'F','O','R'+0x80, |
tomvdb | 0:c52ead8719b3 | 88 | 'I','N','P','U','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 89 | 'P','R','I','N','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 90 | 'P','O','K','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 91 | 'S','T','O','P'+0x80, |
tomvdb | 0:c52ead8719b3 | 92 | 'B','Y','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 93 | 'F','I','L','E','S'+0x80, |
tomvdb | 0:c52ead8719b3 | 94 | 'M','E','M'+0x80, |
tomvdb | 0:c52ead8719b3 | 95 | '?'+ 0x80, |
tomvdb | 0:c52ead8719b3 | 96 | '\''+ 0x80, |
tomvdb | 0:c52ead8719b3 | 97 | 'A','W','R','I','T','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 98 | 'D','W','R','I','T','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 99 | 'D','E','L','A','Y'+0x80, |
tomvdb | 0:c52ead8719b3 | 100 | 'E','N','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 101 | 'R','S','E','E','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 102 | 'C','H','A','I','N'+0x80, |
tomvdb | 0:c52ead8719b3 | 103 | #ifdef ENABLE_TONES |
tomvdb | 0:c52ead8719b3 | 104 | 'T','O','N','E','W'+0x80, |
tomvdb | 0:c52ead8719b3 | 105 | 'T','O','N','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 106 | 'N','O','T','O','N','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 107 | #endif |
tomvdb | 0:c52ead8719b3 | 108 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 109 | 'E','C','H','A','I','N'+0x80, |
tomvdb | 0:c52ead8719b3 | 110 | 'E','L','I','S','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 111 | 'E','L','O','A','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 112 | 'E','F','O','R','M','A','T'+0x80, |
tomvdb | 0:c52ead8719b3 | 113 | 'E','S','A','V','E'+0x80, |
tomvdb | 0:c52ead8719b3 | 114 | #endif |
tomvdb | 0:c52ead8719b3 | 115 | 0 |
tomvdb | 0:c52ead8719b3 | 116 | }; |
tomvdb | 0:c52ead8719b3 | 117 | |
tomvdb | 0:c52ead8719b3 | 118 | // by moving the command list to an enum, we can easily remove sections |
tomvdb | 0:c52ead8719b3 | 119 | // above and below simultaneously to selectively obliterate functionality. |
tomvdb | 0:c52ead8719b3 | 120 | enum { |
tomvdb | 0:c52ead8719b3 | 121 | KW_LIST = 0, |
tomvdb | 0:c52ead8719b3 | 122 | KW_LOAD, KW_NEW, KW_RUN, KW_SAVE, |
tomvdb | 0:c52ead8719b3 | 123 | KW_NEXT, KW_LET, KW_IF, |
tomvdb | 0:c52ead8719b3 | 124 | KW_GOTO, KW_GOSUB, KW_RETURN, |
tomvdb | 0:c52ead8719b3 | 125 | KW_REM, |
tomvdb | 0:c52ead8719b3 | 126 | KW_FOR, |
tomvdb | 0:c52ead8719b3 | 127 | KW_INPUT, KW_PRINT, |
tomvdb | 0:c52ead8719b3 | 128 | KW_POKE, |
tomvdb | 0:c52ead8719b3 | 129 | KW_STOP, KW_BYE, |
tomvdb | 0:c52ead8719b3 | 130 | KW_FILES, |
tomvdb | 0:c52ead8719b3 | 131 | KW_MEM, |
tomvdb | 0:c52ead8719b3 | 132 | KW_QMARK, KW_QUOTE, |
tomvdb | 0:c52ead8719b3 | 133 | KW_AWRITE, KW_DWRITE, |
tomvdb | 0:c52ead8719b3 | 134 | KW_DELAY, |
tomvdb | 0:c52ead8719b3 | 135 | KW_END, |
tomvdb | 0:c52ead8719b3 | 136 | KW_RSEED, |
tomvdb | 0:c52ead8719b3 | 137 | KW_CHAIN, |
tomvdb | 0:c52ead8719b3 | 138 | #ifdef ENABLE_TONES |
tomvdb | 0:c52ead8719b3 | 139 | KW_TONEW, KW_TONE, KW_NOTONE, |
tomvdb | 0:c52ead8719b3 | 140 | #endif |
tomvdb | 0:c52ead8719b3 | 141 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 142 | KW_ECHAIN, KW_ELIST, KW_ELOAD, KW_EFORMAT, KW_ESAVE, |
tomvdb | 0:c52ead8719b3 | 143 | #endif |
tomvdb | 0:c52ead8719b3 | 144 | KW_DEFAULT /* always the final one*/ |
tomvdb | 0:c52ead8719b3 | 145 | }; |
tomvdb | 0:c52ead8719b3 | 146 | |
tomvdb | 0:c52ead8719b3 | 147 | struct stack_for_frame { |
tomvdb | 0:c52ead8719b3 | 148 | char frame_type; |
tomvdb | 0:c52ead8719b3 | 149 | char for_var; |
tomvdb | 0:c52ead8719b3 | 150 | short int terminal; |
tomvdb | 0:c52ead8719b3 | 151 | short int step; |
tomvdb | 0:c52ead8719b3 | 152 | unsigned char *current_line; |
tomvdb | 0:c52ead8719b3 | 153 | unsigned char *txtpos; |
tomvdb | 0:c52ead8719b3 | 154 | }; |
tomvdb | 0:c52ead8719b3 | 155 | |
tomvdb | 0:c52ead8719b3 | 156 | struct stack_gosub_frame { |
tomvdb | 0:c52ead8719b3 | 157 | char frame_type; |
tomvdb | 0:c52ead8719b3 | 158 | unsigned char *current_line; |
tomvdb | 0:c52ead8719b3 | 159 | unsigned char *txtpos; |
tomvdb | 0:c52ead8719b3 | 160 | }; |
tomvdb | 0:c52ead8719b3 | 161 | |
tomvdb | 0:c52ead8719b3 | 162 | static unsigned char func_tab[] = { |
tomvdb | 0:c52ead8719b3 | 163 | 'P','E','E','K'+0x80, |
tomvdb | 0:c52ead8719b3 | 164 | 'A','B','S'+0x80, |
tomvdb | 0:c52ead8719b3 | 165 | 'A','R','E','A','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 166 | 'D','R','E','A','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 167 | 'R','N','D'+0x80, |
tomvdb | 0:c52ead8719b3 | 168 | 0 |
tomvdb | 0:c52ead8719b3 | 169 | }; |
tomvdb | 0:c52ead8719b3 | 170 | #define FUNC_PEEK 0 |
tomvdb | 0:c52ead8719b3 | 171 | #define FUNC_ABS 1 |
tomvdb | 0:c52ead8719b3 | 172 | #define FUNC_AREAD 2 |
tomvdb | 0:c52ead8719b3 | 173 | #define FUNC_DREAD 3 |
tomvdb | 0:c52ead8719b3 | 174 | #define FUNC_RND 4 |
tomvdb | 0:c52ead8719b3 | 175 | #define FUNC_UNKNOWN 5 |
tomvdb | 0:c52ead8719b3 | 176 | |
tomvdb | 0:c52ead8719b3 | 177 | static unsigned char to_tab[] = { |
tomvdb | 0:c52ead8719b3 | 178 | 'T','O'+0x80, |
tomvdb | 0:c52ead8719b3 | 179 | 0 |
tomvdb | 0:c52ead8719b3 | 180 | }; |
tomvdb | 0:c52ead8719b3 | 181 | |
tomvdb | 0:c52ead8719b3 | 182 | static unsigned char step_tab[] = { |
tomvdb | 0:c52ead8719b3 | 183 | 'S','T','E','P'+0x80, |
tomvdb | 0:c52ead8719b3 | 184 | 0 |
tomvdb | 0:c52ead8719b3 | 185 | }; |
tomvdb | 0:c52ead8719b3 | 186 | |
tomvdb | 0:c52ead8719b3 | 187 | static unsigned char relop_tab[] = { |
tomvdb | 0:c52ead8719b3 | 188 | '>','='+0x80, |
tomvdb | 0:c52ead8719b3 | 189 | '<','>'+0x80, |
tomvdb | 0:c52ead8719b3 | 190 | '>'+0x80, |
tomvdb | 0:c52ead8719b3 | 191 | '='+0x80, |
tomvdb | 0:c52ead8719b3 | 192 | '<','='+0x80, |
tomvdb | 0:c52ead8719b3 | 193 | '<'+0x80, |
tomvdb | 0:c52ead8719b3 | 194 | '!','='+0x80, |
tomvdb | 0:c52ead8719b3 | 195 | 0 |
tomvdb | 0:c52ead8719b3 | 196 | }; |
tomvdb | 0:c52ead8719b3 | 197 | |
tomvdb | 0:c52ead8719b3 | 198 | #define RELOP_GE 0 |
tomvdb | 0:c52ead8719b3 | 199 | #define RELOP_NE 1 |
tomvdb | 0:c52ead8719b3 | 200 | #define RELOP_GT 2 |
tomvdb | 0:c52ead8719b3 | 201 | #define RELOP_EQ 3 |
tomvdb | 0:c52ead8719b3 | 202 | #define RELOP_LE 4 |
tomvdb | 0:c52ead8719b3 | 203 | #define RELOP_LT 5 |
tomvdb | 0:c52ead8719b3 | 204 | #define RELOP_NE_BANG 6 |
tomvdb | 0:c52ead8719b3 | 205 | #define RELOP_UNKNOWN 7 |
tomvdb | 0:c52ead8719b3 | 206 | |
tomvdb | 0:c52ead8719b3 | 207 | static unsigned char highlow_tab[] = { |
tomvdb | 0:c52ead8719b3 | 208 | 'H','I','G','H'+0x80, |
tomvdb | 0:c52ead8719b3 | 209 | 'H','I'+0x80, |
tomvdb | 0:c52ead8719b3 | 210 | 'L','O','W'+0x80, |
tomvdb | 0:c52ead8719b3 | 211 | 'L','O'+0x80, |
tomvdb | 0:c52ead8719b3 | 212 | 0 |
tomvdb | 0:c52ead8719b3 | 213 | }; |
tomvdb | 0:c52ead8719b3 | 214 | #define HIGHLOW_HIGH 1 |
tomvdb | 0:c52ead8719b3 | 215 | #define HIGHLOW_UNKNOWN 4 |
tomvdb | 0:c52ead8719b3 | 216 | |
tomvdb | 0:c52ead8719b3 | 217 | #define STACK_SIZE (sizeof(struct stack_for_frame)*5) |
tomvdb | 0:c52ead8719b3 | 218 | #define VAR_SIZE sizeof(short int) // Size of variables in bytes |
tomvdb | 0:c52ead8719b3 | 219 | |
tomvdb | 0:c52ead8719b3 | 220 | static unsigned char *stack_limit; |
tomvdb | 0:c52ead8719b3 | 221 | static unsigned char *program_start; |
tomvdb | 0:c52ead8719b3 | 222 | static unsigned char *program_end; |
tomvdb | 0:c52ead8719b3 | 223 | static unsigned char *stack; // Software stack for things that should go on the CPU stack |
tomvdb | 0:c52ead8719b3 | 224 | static unsigned char *variables_begin; |
tomvdb | 0:c52ead8719b3 | 225 | static unsigned char *current_line; |
tomvdb | 0:c52ead8719b3 | 226 | static unsigned char *sp; |
tomvdb | 0:c52ead8719b3 | 227 | #define STACK_GOSUB_FLAG 'G' |
tomvdb | 0:c52ead8719b3 | 228 | #define STACK_FOR_FLAG 'F' |
tomvdb | 0:c52ead8719b3 | 229 | static unsigned char table_index; |
tomvdb | 0:c52ead8719b3 | 230 | static LINENUM linenum; |
tomvdb | 0:c52ead8719b3 | 231 | |
tomvdb | 0:c52ead8719b3 | 232 | static const unsigned char okmsg[] = "OK"; |
tomvdb | 0:c52ead8719b3 | 233 | static const unsigned char whatmsg[] = "What? "; |
tomvdb | 0:c52ead8719b3 | 234 | static const unsigned char howmsg[] = "How?"; |
tomvdb | 0:c52ead8719b3 | 235 | static const unsigned char sorrymsg[] = "Sorry!"; |
tomvdb | 0:c52ead8719b3 | 236 | static const unsigned char initmsg[] = "TinyBasic Nucleo"; |
tomvdb | 0:c52ead8719b3 | 237 | static const unsigned char memorymsg[] = " bytes free."; |
tomvdb | 0:c52ead8719b3 | 238 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 239 | static const unsigned char eeprommsg[] = " EEProm bytes total."; |
tomvdb | 0:c52ead8719b3 | 240 | static const unsigned char eepromamsg[] = " EEProm bytes available."; |
tomvdb | 0:c52ead8719b3 | 241 | #endif |
tomvdb | 0:c52ead8719b3 | 242 | static const unsigned char breakmsg[] = "break!"; |
tomvdb | 0:c52ead8719b3 | 243 | static const unsigned char unimplimentedmsg[] = "Unimplemented"; |
tomvdb | 0:c52ead8719b3 | 244 | static const unsigned char backspacemsg[] = "\b \b"; |
tomvdb | 0:c52ead8719b3 | 245 | static const unsigned char indentmsg[] = " "; |
tomvdb | 0:c52ead8719b3 | 246 | static const unsigned char sderrormsg[] = "SD card error."; |
tomvdb | 0:c52ead8719b3 | 247 | static const unsigned char sdfilemsg[] = "SD file error."; |
tomvdb | 0:c52ead8719b3 | 248 | static const unsigned char dirextmsg[] = "(dir)"; |
tomvdb | 0:c52ead8719b3 | 249 | static const unsigned char slashmsg[] = "/"; |
tomvdb | 0:c52ead8719b3 | 250 | static const unsigned char spacemsg[] = " "; |
tomvdb | 0:c52ead8719b3 | 251 | |
tomvdb | 0:c52ead8719b3 | 252 | static int inchar(void); |
tomvdb | 0:c52ead8719b3 | 253 | static void outchar(unsigned char c); |
tomvdb | 0:c52ead8719b3 | 254 | static void line_terminator(void); |
tomvdb | 0:c52ead8719b3 | 255 | static short int expression(void); |
tomvdb | 0:c52ead8719b3 | 256 | static unsigned char breakcheck(void); |
tomvdb | 0:c52ead8719b3 | 257 | |
tomvdb | 0:c52ead8719b3 | 258 | |
tomvdb | 0:c52ead8719b3 | 259 | |
tomvdb | 0:c52ead8719b3 | 260 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 261 | static void ignore_blanks(void) |
tomvdb | 0:c52ead8719b3 | 262 | { |
tomvdb | 0:c52ead8719b3 | 263 | while(*txtpos == SPACE || *txtpos == TAB) |
tomvdb | 0:c52ead8719b3 | 264 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 265 | } |
tomvdb | 0:c52ead8719b3 | 266 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 267 | static void scantable(unsigned char *table) |
tomvdb | 0:c52ead8719b3 | 268 | { |
tomvdb | 0:c52ead8719b3 | 269 | int i = 0; |
tomvdb | 0:c52ead8719b3 | 270 | table_index = 0; |
tomvdb | 0:c52ead8719b3 | 271 | while(1) |
tomvdb | 0:c52ead8719b3 | 272 | { |
tomvdb | 0:c52ead8719b3 | 273 | // Run out of table entries? |
tomvdb | 0:c52ead8719b3 | 274 | if(pgm_read_byte( table ) == 0) |
tomvdb | 0:c52ead8719b3 | 275 | return; |
tomvdb | 0:c52ead8719b3 | 276 | |
tomvdb | 0:c52ead8719b3 | 277 | // Do we match this character? |
tomvdb | 0:c52ead8719b3 | 278 | if(txtpos[i] == pgm_read_byte( table )) |
tomvdb | 0:c52ead8719b3 | 279 | { |
tomvdb | 0:c52ead8719b3 | 280 | i++; |
tomvdb | 0:c52ead8719b3 | 281 | table++; |
tomvdb | 0:c52ead8719b3 | 282 | } |
tomvdb | 0:c52ead8719b3 | 283 | else |
tomvdb | 0:c52ead8719b3 | 284 | { |
tomvdb | 0:c52ead8719b3 | 285 | // do we match the last character of keywork (with 0x80 added)? If so, return |
tomvdb | 0:c52ead8719b3 | 286 | if(txtpos[i]+0x80 == pgm_read_byte( table )) |
tomvdb | 0:c52ead8719b3 | 287 | { |
tomvdb | 0:c52ead8719b3 | 288 | txtpos += i+1; // Advance the pointer to following the keyword |
tomvdb | 0:c52ead8719b3 | 289 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 290 | return; |
tomvdb | 0:c52ead8719b3 | 291 | } |
tomvdb | 0:c52ead8719b3 | 292 | |
tomvdb | 0:c52ead8719b3 | 293 | // Forward to the end of this keyword |
tomvdb | 0:c52ead8719b3 | 294 | while((pgm_read_byte( table ) & 0x80) == 0) |
tomvdb | 0:c52ead8719b3 | 295 | table++; |
tomvdb | 0:c52ead8719b3 | 296 | |
tomvdb | 0:c52ead8719b3 | 297 | // Now move on to the first character of the next word, and reset the position index |
tomvdb | 0:c52ead8719b3 | 298 | table++; |
tomvdb | 0:c52ead8719b3 | 299 | table_index++; |
tomvdb | 0:c52ead8719b3 | 300 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 301 | i = 0; |
tomvdb | 0:c52ead8719b3 | 302 | } |
tomvdb | 0:c52ead8719b3 | 303 | } |
tomvdb | 0:c52ead8719b3 | 304 | } |
tomvdb | 0:c52ead8719b3 | 305 | |
tomvdb | 0:c52ead8719b3 | 306 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 307 | static void pushb(unsigned char b) |
tomvdb | 0:c52ead8719b3 | 308 | { |
tomvdb | 0:c52ead8719b3 | 309 | sp--; |
tomvdb | 0:c52ead8719b3 | 310 | *sp = b; |
tomvdb | 0:c52ead8719b3 | 311 | } |
tomvdb | 0:c52ead8719b3 | 312 | |
tomvdb | 0:c52ead8719b3 | 313 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 314 | static unsigned char popb() |
tomvdb | 0:c52ead8719b3 | 315 | { |
tomvdb | 0:c52ead8719b3 | 316 | unsigned char b; |
tomvdb | 0:c52ead8719b3 | 317 | b = *sp; |
tomvdb | 0:c52ead8719b3 | 318 | sp++; |
tomvdb | 0:c52ead8719b3 | 319 | return b; |
tomvdb | 0:c52ead8719b3 | 320 | } |
tomvdb | 0:c52ead8719b3 | 321 | |
tomvdb | 0:c52ead8719b3 | 322 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 323 | void printnum(int num) |
tomvdb | 0:c52ead8719b3 | 324 | { |
tomvdb | 0:c52ead8719b3 | 325 | int digits = 0; |
tomvdb | 0:c52ead8719b3 | 326 | |
tomvdb | 0:c52ead8719b3 | 327 | if(num < 0) |
tomvdb | 0:c52ead8719b3 | 328 | { |
tomvdb | 0:c52ead8719b3 | 329 | num = -num; |
tomvdb | 0:c52ead8719b3 | 330 | outchar('-'); |
tomvdb | 0:c52ead8719b3 | 331 | } |
tomvdb | 0:c52ead8719b3 | 332 | do { |
tomvdb | 0:c52ead8719b3 | 333 | pushb(num%10+'0'); |
tomvdb | 0:c52ead8719b3 | 334 | num = num/10; |
tomvdb | 0:c52ead8719b3 | 335 | digits++; |
tomvdb | 0:c52ead8719b3 | 336 | } |
tomvdb | 0:c52ead8719b3 | 337 | while (num > 0); |
tomvdb | 0:c52ead8719b3 | 338 | |
tomvdb | 0:c52ead8719b3 | 339 | while(digits > 0) |
tomvdb | 0:c52ead8719b3 | 340 | { |
tomvdb | 0:c52ead8719b3 | 341 | outchar(popb()); |
tomvdb | 0:c52ead8719b3 | 342 | digits--; |
tomvdb | 0:c52ead8719b3 | 343 | } |
tomvdb | 0:c52ead8719b3 | 344 | } |
tomvdb | 0:c52ead8719b3 | 345 | |
tomvdb | 0:c52ead8719b3 | 346 | void printUnum(unsigned int num) |
tomvdb | 0:c52ead8719b3 | 347 | { |
tomvdb | 0:c52ead8719b3 | 348 | int digits = 0; |
tomvdb | 0:c52ead8719b3 | 349 | |
tomvdb | 0:c52ead8719b3 | 350 | do { |
tomvdb | 0:c52ead8719b3 | 351 | pushb(num%10+'0'); |
tomvdb | 0:c52ead8719b3 | 352 | num = num/10; |
tomvdb | 0:c52ead8719b3 | 353 | digits++; |
tomvdb | 0:c52ead8719b3 | 354 | } |
tomvdb | 0:c52ead8719b3 | 355 | while (num > 0); |
tomvdb | 0:c52ead8719b3 | 356 | |
tomvdb | 0:c52ead8719b3 | 357 | while(digits > 0) |
tomvdb | 0:c52ead8719b3 | 358 | { |
tomvdb | 0:c52ead8719b3 | 359 | outchar(popb()); |
tomvdb | 0:c52ead8719b3 | 360 | digits--; |
tomvdb | 0:c52ead8719b3 | 361 | } |
tomvdb | 0:c52ead8719b3 | 362 | } |
tomvdb | 0:c52ead8719b3 | 363 | |
tomvdb | 0:c52ead8719b3 | 364 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 365 | static unsigned short testnum(void) |
tomvdb | 0:c52ead8719b3 | 366 | { |
tomvdb | 0:c52ead8719b3 | 367 | unsigned short num = 0; |
tomvdb | 0:c52ead8719b3 | 368 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 369 | |
tomvdb | 0:c52ead8719b3 | 370 | while(*txtpos>= '0' && *txtpos <= '9' ) |
tomvdb | 0:c52ead8719b3 | 371 | { |
tomvdb | 0:c52ead8719b3 | 372 | // Trap overflows |
tomvdb | 0:c52ead8719b3 | 373 | if(num >= 0xFFFF/10) |
tomvdb | 0:c52ead8719b3 | 374 | { |
tomvdb | 0:c52ead8719b3 | 375 | num = 0xFFFF; |
tomvdb | 0:c52ead8719b3 | 376 | break; |
tomvdb | 0:c52ead8719b3 | 377 | } |
tomvdb | 0:c52ead8719b3 | 378 | |
tomvdb | 0:c52ead8719b3 | 379 | num = num *10 + *txtpos - '0'; |
tomvdb | 0:c52ead8719b3 | 380 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 381 | } |
tomvdb | 0:c52ead8719b3 | 382 | return num; |
tomvdb | 0:c52ead8719b3 | 383 | } |
tomvdb | 0:c52ead8719b3 | 384 | |
tomvdb | 0:c52ead8719b3 | 385 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 386 | static unsigned char print_quoted_string(void) |
tomvdb | 0:c52ead8719b3 | 387 | { |
tomvdb | 0:c52ead8719b3 | 388 | int i=0; |
tomvdb | 0:c52ead8719b3 | 389 | unsigned char delim = *txtpos; |
tomvdb | 0:c52ead8719b3 | 390 | if(delim != '"' && delim != '\'') |
tomvdb | 0:c52ead8719b3 | 391 | return 0; |
tomvdb | 0:c52ead8719b3 | 392 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 393 | |
tomvdb | 0:c52ead8719b3 | 394 | // Check we have a closing delimiter |
tomvdb | 0:c52ead8719b3 | 395 | while(txtpos[i] != delim) |
tomvdb | 0:c52ead8719b3 | 396 | { |
tomvdb | 0:c52ead8719b3 | 397 | if(txtpos[i] == NL) |
tomvdb | 0:c52ead8719b3 | 398 | return 0; |
tomvdb | 0:c52ead8719b3 | 399 | i++; |
tomvdb | 0:c52ead8719b3 | 400 | } |
tomvdb | 0:c52ead8719b3 | 401 | |
tomvdb | 0:c52ead8719b3 | 402 | // Print the characters |
tomvdb | 0:c52ead8719b3 | 403 | while(*txtpos != delim) |
tomvdb | 0:c52ead8719b3 | 404 | { |
tomvdb | 0:c52ead8719b3 | 405 | outchar(*txtpos); |
tomvdb | 0:c52ead8719b3 | 406 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 407 | } |
tomvdb | 0:c52ead8719b3 | 408 | txtpos++; // Skip over the last delimiter |
tomvdb | 0:c52ead8719b3 | 409 | |
tomvdb | 0:c52ead8719b3 | 410 | return 1; |
tomvdb | 0:c52ead8719b3 | 411 | } |
tomvdb | 0:c52ead8719b3 | 412 | |
tomvdb | 0:c52ead8719b3 | 413 | |
tomvdb | 0:c52ead8719b3 | 414 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 415 | void printmsgNoNL(const unsigned char *msg) |
tomvdb | 0:c52ead8719b3 | 416 | { |
tomvdb | 0:c52ead8719b3 | 417 | while( pgm_read_byte( msg ) != 0 ) { |
tomvdb | 0:c52ead8719b3 | 418 | outchar( pgm_read_byte( msg++ ) ); |
tomvdb | 0:c52ead8719b3 | 419 | }; |
tomvdb | 0:c52ead8719b3 | 420 | } |
tomvdb | 0:c52ead8719b3 | 421 | |
tomvdb | 0:c52ead8719b3 | 422 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 423 | void printmsg(const unsigned char *msg) |
tomvdb | 0:c52ead8719b3 | 424 | { |
tomvdb | 0:c52ead8719b3 | 425 | printmsgNoNL(msg); |
tomvdb | 0:c52ead8719b3 | 426 | line_terminator(); |
tomvdb | 0:c52ead8719b3 | 427 | } |
tomvdb | 0:c52ead8719b3 | 428 | |
tomvdb | 0:c52ead8719b3 | 429 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 430 | static void getln(char prompt) |
tomvdb | 0:c52ead8719b3 | 431 | { |
tomvdb | 0:c52ead8719b3 | 432 | outchar(prompt); |
tomvdb | 0:c52ead8719b3 | 433 | txtpos = program_end+sizeof(LINENUM); |
tomvdb | 0:c52ead8719b3 | 434 | |
tomvdb | 0:c52ead8719b3 | 435 | while(1) |
tomvdb | 0:c52ead8719b3 | 436 | { |
tomvdb | 0:c52ead8719b3 | 437 | char c = inchar(); |
tomvdb | 0:c52ead8719b3 | 438 | switch(c) |
tomvdb | 0:c52ead8719b3 | 439 | { |
tomvdb | 0:c52ead8719b3 | 440 | case NL: |
tomvdb | 0:c52ead8719b3 | 441 | //break; |
tomvdb | 0:c52ead8719b3 | 442 | case CR: |
tomvdb | 0:c52ead8719b3 | 443 | line_terminator(); |
tomvdb | 0:c52ead8719b3 | 444 | // Terminate all strings with a NL |
tomvdb | 0:c52ead8719b3 | 445 | txtpos[0] = NL; |
tomvdb | 0:c52ead8719b3 | 446 | return; |
tomvdb | 0:c52ead8719b3 | 447 | case CTRLH: |
tomvdb | 0:c52ead8719b3 | 448 | if(txtpos == program_end) |
tomvdb | 0:c52ead8719b3 | 449 | break; |
tomvdb | 0:c52ead8719b3 | 450 | txtpos--; |
tomvdb | 0:c52ead8719b3 | 451 | |
tomvdb | 0:c52ead8719b3 | 452 | printmsg(backspacemsg); |
tomvdb | 0:c52ead8719b3 | 453 | break; |
tomvdb | 0:c52ead8719b3 | 454 | default: |
tomvdb | 0:c52ead8719b3 | 455 | // We need to leave at least one space to allow us to shuffle the line into order |
tomvdb | 0:c52ead8719b3 | 456 | if(txtpos == variables_begin-2) |
tomvdb | 0:c52ead8719b3 | 457 | outchar(BELL); |
tomvdb | 0:c52ead8719b3 | 458 | else |
tomvdb | 0:c52ead8719b3 | 459 | { |
tomvdb | 0:c52ead8719b3 | 460 | txtpos[0] = c; |
tomvdb | 0:c52ead8719b3 | 461 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 462 | outchar(c); |
tomvdb | 0:c52ead8719b3 | 463 | } |
tomvdb | 0:c52ead8719b3 | 464 | } |
tomvdb | 0:c52ead8719b3 | 465 | } |
tomvdb | 0:c52ead8719b3 | 466 | } |
tomvdb | 0:c52ead8719b3 | 467 | |
tomvdb | 0:c52ead8719b3 | 468 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 469 | static unsigned char *findline(void) |
tomvdb | 0:c52ead8719b3 | 470 | { |
tomvdb | 0:c52ead8719b3 | 471 | unsigned char *line = program_start; |
tomvdb | 0:c52ead8719b3 | 472 | while(1) |
tomvdb | 0:c52ead8719b3 | 473 | { |
tomvdb | 0:c52ead8719b3 | 474 | if(line == program_end) |
tomvdb | 0:c52ead8719b3 | 475 | return line; |
tomvdb | 0:c52ead8719b3 | 476 | |
tomvdb | 0:c52ead8719b3 | 477 | if(((LINENUM *)line)[0] >= linenum) |
tomvdb | 0:c52ead8719b3 | 478 | return line; |
tomvdb | 0:c52ead8719b3 | 479 | |
tomvdb | 0:c52ead8719b3 | 480 | // Add the line length onto the current address, to get to the next line; |
tomvdb | 0:c52ead8719b3 | 481 | line += line[sizeof(LINENUM)]; |
tomvdb | 0:c52ead8719b3 | 482 | } |
tomvdb | 0:c52ead8719b3 | 483 | } |
tomvdb | 0:c52ead8719b3 | 484 | |
tomvdb | 0:c52ead8719b3 | 485 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 486 | static void toUppercaseBuffer(void) |
tomvdb | 0:c52ead8719b3 | 487 | { |
tomvdb | 0:c52ead8719b3 | 488 | unsigned char *c = program_end+sizeof(LINENUM); |
tomvdb | 0:c52ead8719b3 | 489 | unsigned char quote = 0; |
tomvdb | 0:c52ead8719b3 | 490 | |
tomvdb | 0:c52ead8719b3 | 491 | while(*c != NL) |
tomvdb | 0:c52ead8719b3 | 492 | { |
tomvdb | 0:c52ead8719b3 | 493 | // Are we in a quoted string? |
tomvdb | 0:c52ead8719b3 | 494 | if(*c == quote) |
tomvdb | 0:c52ead8719b3 | 495 | quote = 0; |
tomvdb | 0:c52ead8719b3 | 496 | else if(*c == '"' || *c == '\'') |
tomvdb | 0:c52ead8719b3 | 497 | quote = *c; |
tomvdb | 0:c52ead8719b3 | 498 | else if(quote == 0 && *c >= 'a' && *c <= 'z') |
tomvdb | 0:c52ead8719b3 | 499 | *c = *c + 'A' - 'a'; |
tomvdb | 0:c52ead8719b3 | 500 | c++; |
tomvdb | 0:c52ead8719b3 | 501 | } |
tomvdb | 0:c52ead8719b3 | 502 | } |
tomvdb | 0:c52ead8719b3 | 503 | |
tomvdb | 0:c52ead8719b3 | 504 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 505 | void printline() |
tomvdb | 0:c52ead8719b3 | 506 | { |
tomvdb | 0:c52ead8719b3 | 507 | LINENUM line_num; |
tomvdb | 0:c52ead8719b3 | 508 | |
tomvdb | 0:c52ead8719b3 | 509 | line_num = *((LINENUM *)(list_line)); |
tomvdb | 0:c52ead8719b3 | 510 | list_line += sizeof(LINENUM) + sizeof(char); |
tomvdb | 0:c52ead8719b3 | 511 | |
tomvdb | 0:c52ead8719b3 | 512 | // Output the line */ |
tomvdb | 0:c52ead8719b3 | 513 | printnum(line_num); |
tomvdb | 0:c52ead8719b3 | 514 | outchar(' '); |
tomvdb | 0:c52ead8719b3 | 515 | while(*list_line != NL) |
tomvdb | 0:c52ead8719b3 | 516 | { |
tomvdb | 0:c52ead8719b3 | 517 | outchar(*list_line); |
tomvdb | 0:c52ead8719b3 | 518 | list_line++; |
tomvdb | 0:c52ead8719b3 | 519 | } |
tomvdb | 0:c52ead8719b3 | 520 | list_line++; |
tomvdb | 0:c52ead8719b3 | 521 | line_terminator(); |
tomvdb | 0:c52ead8719b3 | 522 | } |
tomvdb | 0:c52ead8719b3 | 523 | |
tomvdb | 0:c52ead8719b3 | 524 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 525 | static short int expr4(void) |
tomvdb | 0:c52ead8719b3 | 526 | { |
tomvdb | 0:c52ead8719b3 | 527 | // fix provided by Jurg Wullschleger wullschleger@gmail.com |
tomvdb | 0:c52ead8719b3 | 528 | // fixes whitespace and unary operations |
tomvdb | 0:c52ead8719b3 | 529 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 530 | |
tomvdb | 0:c52ead8719b3 | 531 | if( *txtpos == '-' ) { |
tomvdb | 0:c52ead8719b3 | 532 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 533 | return -expr4(); |
tomvdb | 0:c52ead8719b3 | 534 | } |
tomvdb | 0:c52ead8719b3 | 535 | // end fix |
tomvdb | 0:c52ead8719b3 | 536 | |
tomvdb | 0:c52ead8719b3 | 537 | if(*txtpos == '0') |
tomvdb | 0:c52ead8719b3 | 538 | { |
tomvdb | 0:c52ead8719b3 | 539 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 540 | return 0; |
tomvdb | 0:c52ead8719b3 | 541 | } |
tomvdb | 0:c52ead8719b3 | 542 | |
tomvdb | 0:c52ead8719b3 | 543 | if(*txtpos >= '1' && *txtpos <= '9') |
tomvdb | 0:c52ead8719b3 | 544 | { |
tomvdb | 0:c52ead8719b3 | 545 | short int a = 0; |
tomvdb | 0:c52ead8719b3 | 546 | do { |
tomvdb | 0:c52ead8719b3 | 547 | a = a*10 + *txtpos - '0'; |
tomvdb | 0:c52ead8719b3 | 548 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 549 | } |
tomvdb | 0:c52ead8719b3 | 550 | while(*txtpos >= '0' && *txtpos <= '9'); |
tomvdb | 0:c52ead8719b3 | 551 | return a; |
tomvdb | 0:c52ead8719b3 | 552 | } |
tomvdb | 0:c52ead8719b3 | 553 | |
tomvdb | 0:c52ead8719b3 | 554 | // Is it a function or variable reference? |
tomvdb | 0:c52ead8719b3 | 555 | if(txtpos[0] >= 'A' && txtpos[0] <= 'Z') |
tomvdb | 0:c52ead8719b3 | 556 | { |
tomvdb | 0:c52ead8719b3 | 557 | short int a; |
tomvdb | 0:c52ead8719b3 | 558 | // Is it a variable reference (single alpha) |
tomvdb | 0:c52ead8719b3 | 559 | if(txtpos[1] < 'A' || txtpos[1] > 'Z') |
tomvdb | 0:c52ead8719b3 | 560 | { |
tomvdb | 0:c52ead8719b3 | 561 | a = ((short int *)variables_begin)[*txtpos - 'A']; |
tomvdb | 0:c52ead8719b3 | 562 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 563 | return a; |
tomvdb | 0:c52ead8719b3 | 564 | } |
tomvdb | 0:c52ead8719b3 | 565 | |
tomvdb | 0:c52ead8719b3 | 566 | // Is it a function with a single parameter |
tomvdb | 0:c52ead8719b3 | 567 | scantable(func_tab); |
tomvdb | 0:c52ead8719b3 | 568 | if(table_index == FUNC_UNKNOWN) |
tomvdb | 0:c52ead8719b3 | 569 | goto expr4_error; |
tomvdb | 0:c52ead8719b3 | 570 | |
tomvdb | 0:c52ead8719b3 | 571 | unsigned char f = table_index; |
tomvdb | 0:c52ead8719b3 | 572 | |
tomvdb | 0:c52ead8719b3 | 573 | if(*txtpos != '(') |
tomvdb | 0:c52ead8719b3 | 574 | goto expr4_error; |
tomvdb | 0:c52ead8719b3 | 575 | |
tomvdb | 0:c52ead8719b3 | 576 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 577 | a = expression(); |
tomvdb | 0:c52ead8719b3 | 578 | if(*txtpos != ')') |
tomvdb | 0:c52ead8719b3 | 579 | goto expr4_error; |
tomvdb | 0:c52ead8719b3 | 580 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 581 | switch(f) |
tomvdb | 0:c52ead8719b3 | 582 | { |
tomvdb | 0:c52ead8719b3 | 583 | case FUNC_PEEK: |
tomvdb | 0:c52ead8719b3 | 584 | return program[a]; |
tomvdb | 0:c52ead8719b3 | 585 | |
tomvdb | 0:c52ead8719b3 | 586 | case FUNC_ABS: |
tomvdb | 0:c52ead8719b3 | 587 | if(a < 0) |
tomvdb | 0:c52ead8719b3 | 588 | return -a; |
tomvdb | 0:c52ead8719b3 | 589 | return a; |
tomvdb | 0:c52ead8719b3 | 590 | |
tomvdb | 0:c52ead8719b3 | 591 | /* |
tomvdb | 0:c52ead8719b3 | 592 | // fix |
tomvdb | 0:c52ead8719b3 | 593 | #ifdef ARDUINO |
tomvdb | 0:c52ead8719b3 | 594 | case FUNC_AREAD: |
tomvdb | 0:c52ead8719b3 | 595 | pinMode( a, INPUT ); |
tomvdb | 0:c52ead8719b3 | 596 | return analogRead( a ); |
tomvdb | 0:c52ead8719b3 | 597 | case FUNC_DREAD: |
tomvdb | 0:c52ead8719b3 | 598 | pinMode( a, INPUT ); |
tomvdb | 0:c52ead8719b3 | 599 | return digitalRead( a ); |
tomvdb | 0:c52ead8719b3 | 600 | #endif |
tomvdb | 0:c52ead8719b3 | 601 | */ |
tomvdb | 0:c52ead8719b3 | 602 | |
tomvdb | 0:c52ead8719b3 | 603 | case FUNC_RND: |
tomvdb | 0:c52ead8719b3 | 604 | return 0; |
tomvdb | 0:c52ead8719b3 | 605 | /* |
tomvdb | 0:c52ead8719b3 | 606 | #ifdef ARDUINO |
tomvdb | 0:c52ead8719b3 | 607 | return( random( a )); |
tomvdb | 0:c52ead8719b3 | 608 | #else |
tomvdb | 0:c52ead8719b3 | 609 | return( rand() % a ); |
tomvdb | 0:c52ead8719b3 | 610 | #endif |
tomvdb | 0:c52ead8719b3 | 611 | */ |
tomvdb | 0:c52ead8719b3 | 612 | } |
tomvdb | 0:c52ead8719b3 | 613 | } |
tomvdb | 0:c52ead8719b3 | 614 | |
tomvdb | 0:c52ead8719b3 | 615 | if(*txtpos == '(') |
tomvdb | 0:c52ead8719b3 | 616 | { |
tomvdb | 0:c52ead8719b3 | 617 | short int a; |
tomvdb | 0:c52ead8719b3 | 618 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 619 | a = expression(); |
tomvdb | 0:c52ead8719b3 | 620 | if(*txtpos != ')') |
tomvdb | 0:c52ead8719b3 | 621 | goto expr4_error; |
tomvdb | 0:c52ead8719b3 | 622 | |
tomvdb | 0:c52ead8719b3 | 623 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 624 | return a; |
tomvdb | 0:c52ead8719b3 | 625 | } |
tomvdb | 0:c52ead8719b3 | 626 | |
tomvdb | 0:c52ead8719b3 | 627 | expr4_error: |
tomvdb | 0:c52ead8719b3 | 628 | expression_error = 1; |
tomvdb | 0:c52ead8719b3 | 629 | return 0; |
tomvdb | 0:c52ead8719b3 | 630 | |
tomvdb | 0:c52ead8719b3 | 631 | } |
tomvdb | 0:c52ead8719b3 | 632 | |
tomvdb | 0:c52ead8719b3 | 633 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 634 | static short int expr3(void) |
tomvdb | 0:c52ead8719b3 | 635 | { |
tomvdb | 0:c52ead8719b3 | 636 | short int a,b; |
tomvdb | 0:c52ead8719b3 | 637 | |
tomvdb | 0:c52ead8719b3 | 638 | a = expr4(); |
tomvdb | 0:c52ead8719b3 | 639 | |
tomvdb | 0:c52ead8719b3 | 640 | ignore_blanks(); // fix for eg: 100 a = a + 1 |
tomvdb | 0:c52ead8719b3 | 641 | |
tomvdb | 0:c52ead8719b3 | 642 | while(1) |
tomvdb | 0:c52ead8719b3 | 643 | { |
tomvdb | 0:c52ead8719b3 | 644 | if(*txtpos == '*') |
tomvdb | 0:c52ead8719b3 | 645 | { |
tomvdb | 0:c52ead8719b3 | 646 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 647 | b = expr4(); |
tomvdb | 0:c52ead8719b3 | 648 | a *= b; |
tomvdb | 0:c52ead8719b3 | 649 | } |
tomvdb | 0:c52ead8719b3 | 650 | else if(*txtpos == '/') |
tomvdb | 0:c52ead8719b3 | 651 | { |
tomvdb | 0:c52ead8719b3 | 652 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 653 | b = expr4(); |
tomvdb | 0:c52ead8719b3 | 654 | if(b != 0) |
tomvdb | 0:c52ead8719b3 | 655 | a /= b; |
tomvdb | 0:c52ead8719b3 | 656 | else |
tomvdb | 0:c52ead8719b3 | 657 | expression_error = 1; |
tomvdb | 0:c52ead8719b3 | 658 | } |
tomvdb | 0:c52ead8719b3 | 659 | else |
tomvdb | 0:c52ead8719b3 | 660 | return a; |
tomvdb | 0:c52ead8719b3 | 661 | } |
tomvdb | 0:c52ead8719b3 | 662 | } |
tomvdb | 0:c52ead8719b3 | 663 | |
tomvdb | 0:c52ead8719b3 | 664 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 665 | static short int expr2(void) |
tomvdb | 0:c52ead8719b3 | 666 | { |
tomvdb | 0:c52ead8719b3 | 667 | short int a,b; |
tomvdb | 0:c52ead8719b3 | 668 | |
tomvdb | 0:c52ead8719b3 | 669 | if(*txtpos == '-' || *txtpos == '+') |
tomvdb | 0:c52ead8719b3 | 670 | a = 0; |
tomvdb | 0:c52ead8719b3 | 671 | else |
tomvdb | 0:c52ead8719b3 | 672 | a = expr3(); |
tomvdb | 0:c52ead8719b3 | 673 | |
tomvdb | 0:c52ead8719b3 | 674 | while(1) |
tomvdb | 0:c52ead8719b3 | 675 | { |
tomvdb | 0:c52ead8719b3 | 676 | if(*txtpos == '-') |
tomvdb | 0:c52ead8719b3 | 677 | { |
tomvdb | 0:c52ead8719b3 | 678 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 679 | b = expr3(); |
tomvdb | 0:c52ead8719b3 | 680 | a -= b; |
tomvdb | 0:c52ead8719b3 | 681 | } |
tomvdb | 0:c52ead8719b3 | 682 | else if(*txtpos == '+') |
tomvdb | 0:c52ead8719b3 | 683 | { |
tomvdb | 0:c52ead8719b3 | 684 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 685 | b = expr3(); |
tomvdb | 0:c52ead8719b3 | 686 | a += b; |
tomvdb | 0:c52ead8719b3 | 687 | } |
tomvdb | 0:c52ead8719b3 | 688 | else |
tomvdb | 0:c52ead8719b3 | 689 | return a; |
tomvdb | 0:c52ead8719b3 | 690 | } |
tomvdb | 0:c52ead8719b3 | 691 | } |
tomvdb | 0:c52ead8719b3 | 692 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 693 | static short int expression(void) |
tomvdb | 0:c52ead8719b3 | 694 | { |
tomvdb | 0:c52ead8719b3 | 695 | short int a,b; |
tomvdb | 0:c52ead8719b3 | 696 | |
tomvdb | 0:c52ead8719b3 | 697 | a = expr2(); |
tomvdb | 0:c52ead8719b3 | 698 | |
tomvdb | 0:c52ead8719b3 | 699 | // Check if we have an error |
tomvdb | 0:c52ead8719b3 | 700 | if(expression_error) return a; |
tomvdb | 0:c52ead8719b3 | 701 | |
tomvdb | 0:c52ead8719b3 | 702 | scantable(relop_tab); |
tomvdb | 0:c52ead8719b3 | 703 | if(table_index == RELOP_UNKNOWN) |
tomvdb | 0:c52ead8719b3 | 704 | return a; |
tomvdb | 0:c52ead8719b3 | 705 | |
tomvdb | 0:c52ead8719b3 | 706 | switch(table_index) |
tomvdb | 0:c52ead8719b3 | 707 | { |
tomvdb | 0:c52ead8719b3 | 708 | case RELOP_GE: |
tomvdb | 0:c52ead8719b3 | 709 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 710 | if(a >= b) return 1; |
tomvdb | 0:c52ead8719b3 | 711 | break; |
tomvdb | 0:c52ead8719b3 | 712 | case RELOP_NE: |
tomvdb | 0:c52ead8719b3 | 713 | case RELOP_NE_BANG: |
tomvdb | 0:c52ead8719b3 | 714 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 715 | if(a != b) return 1; |
tomvdb | 0:c52ead8719b3 | 716 | break; |
tomvdb | 0:c52ead8719b3 | 717 | case RELOP_GT: |
tomvdb | 0:c52ead8719b3 | 718 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 719 | if(a > b) return 1; |
tomvdb | 0:c52ead8719b3 | 720 | break; |
tomvdb | 0:c52ead8719b3 | 721 | case RELOP_EQ: |
tomvdb | 0:c52ead8719b3 | 722 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 723 | if(a == b) return 1; |
tomvdb | 0:c52ead8719b3 | 724 | break; |
tomvdb | 0:c52ead8719b3 | 725 | case RELOP_LE: |
tomvdb | 0:c52ead8719b3 | 726 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 727 | if(a <= b) return 1; |
tomvdb | 0:c52ead8719b3 | 728 | break; |
tomvdb | 0:c52ead8719b3 | 729 | case RELOP_LT: |
tomvdb | 0:c52ead8719b3 | 730 | b = expr2(); |
tomvdb | 0:c52ead8719b3 | 731 | if(a < b) return 1; |
tomvdb | 0:c52ead8719b3 | 732 | break; |
tomvdb | 0:c52ead8719b3 | 733 | } |
tomvdb | 0:c52ead8719b3 | 734 | return 0; |
tomvdb | 0:c52ead8719b3 | 735 | } |
tomvdb | 0:c52ead8719b3 | 736 | |
tomvdb | 0:c52ead8719b3 | 737 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 738 | void loop() |
tomvdb | 0:c52ead8719b3 | 739 | { |
tomvdb | 0:c52ead8719b3 | 740 | unsigned char *start; |
tomvdb | 0:c52ead8719b3 | 741 | unsigned char *newEnd; |
tomvdb | 0:c52ead8719b3 | 742 | unsigned char linelen; |
tomvdb | 0:c52ead8719b3 | 743 | boolean isDigital; |
tomvdb | 0:c52ead8719b3 | 744 | boolean alsoWait = false; |
tomvdb | 0:c52ead8719b3 | 745 | int val; |
tomvdb | 0:c52ead8719b3 | 746 | |
tomvdb | 0:c52ead8719b3 | 747 | #ifdef ENABLE_TONES |
tomvdb | 0:c52ead8719b3 | 748 | noTone( kPiezoPin ); |
tomvdb | 0:c52ead8719b3 | 749 | #endif |
tomvdb | 0:c52ead8719b3 | 750 | |
tomvdb | 0:c52ead8719b3 | 751 | program_start = program; |
tomvdb | 0:c52ead8719b3 | 752 | program_end = program_start; |
tomvdb | 0:c52ead8719b3 | 753 | sp = program+sizeof(program); // Needed for printnum |
tomvdb | 0:c52ead8719b3 | 754 | stack_limit = program+sizeof(program)-STACK_SIZE; |
tomvdb | 0:c52ead8719b3 | 755 | variables_begin = stack_limit - 27*VAR_SIZE; |
tomvdb | 0:c52ead8719b3 | 756 | |
tomvdb | 0:c52ead8719b3 | 757 | // memory free |
tomvdb | 0:c52ead8719b3 | 758 | printnum(variables_begin-program_end); |
tomvdb | 0:c52ead8719b3 | 759 | printmsg(memorymsg); |
tomvdb | 0:c52ead8719b3 | 760 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 761 | // eprom size |
tomvdb | 0:c52ead8719b3 | 762 | printnum( E2END+1 ); |
tomvdb | 0:c52ead8719b3 | 763 | printmsg( eeprommsg ); |
tomvdb | 0:c52ead8719b3 | 764 | #endif /* ENABLE_EEPROM */ |
tomvdb | 0:c52ead8719b3 | 765 | |
tomvdb | 0:c52ead8719b3 | 766 | warmstart: |
tomvdb | 0:c52ead8719b3 | 767 | // this signifies that it is running in 'direct' mode. |
tomvdb | 0:c52ead8719b3 | 768 | current_line = 0; |
tomvdb | 0:c52ead8719b3 | 769 | sp = program+sizeof(program); |
tomvdb | 0:c52ead8719b3 | 770 | printmsg(okmsg); |
tomvdb | 0:c52ead8719b3 | 771 | |
tomvdb | 0:c52ead8719b3 | 772 | prompt: |
tomvdb | 0:c52ead8719b3 | 773 | if( triggerRun ){ |
tomvdb | 0:c52ead8719b3 | 774 | triggerRun = false; |
tomvdb | 0:c52ead8719b3 | 775 | current_line = program_start; |
tomvdb | 0:c52ead8719b3 | 776 | goto execline; |
tomvdb | 0:c52ead8719b3 | 777 | } |
tomvdb | 0:c52ead8719b3 | 778 | |
tomvdb | 0:c52ead8719b3 | 779 | getln( '>' ); |
tomvdb | 0:c52ead8719b3 | 780 | toUppercaseBuffer(); |
tomvdb | 0:c52ead8719b3 | 781 | |
tomvdb | 0:c52ead8719b3 | 782 | txtpos = program_end+sizeof(unsigned short); |
tomvdb | 0:c52ead8719b3 | 783 | |
tomvdb | 0:c52ead8719b3 | 784 | // Find the end of the freshly entered line |
tomvdb | 0:c52ead8719b3 | 785 | while(*txtpos != NL) |
tomvdb | 0:c52ead8719b3 | 786 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 787 | |
tomvdb | 0:c52ead8719b3 | 788 | // Move it to the end of program_memory |
tomvdb | 0:c52ead8719b3 | 789 | { |
tomvdb | 0:c52ead8719b3 | 790 | unsigned char *dest; |
tomvdb | 0:c52ead8719b3 | 791 | dest = variables_begin-1; |
tomvdb | 0:c52ead8719b3 | 792 | while(1) |
tomvdb | 0:c52ead8719b3 | 793 | { |
tomvdb | 0:c52ead8719b3 | 794 | *dest = *txtpos; |
tomvdb | 0:c52ead8719b3 | 795 | if(txtpos == program_end+sizeof(unsigned short)) |
tomvdb | 0:c52ead8719b3 | 796 | break; |
tomvdb | 0:c52ead8719b3 | 797 | dest--; |
tomvdb | 0:c52ead8719b3 | 798 | txtpos--; |
tomvdb | 0:c52ead8719b3 | 799 | } |
tomvdb | 0:c52ead8719b3 | 800 | txtpos = dest; |
tomvdb | 0:c52ead8719b3 | 801 | } |
tomvdb | 0:c52ead8719b3 | 802 | |
tomvdb | 0:c52ead8719b3 | 803 | // Now see if we have a line number |
tomvdb | 0:c52ead8719b3 | 804 | linenum = testnum(); |
tomvdb | 0:c52ead8719b3 | 805 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 806 | if(linenum == 0) |
tomvdb | 0:c52ead8719b3 | 807 | goto direct; |
tomvdb | 0:c52ead8719b3 | 808 | |
tomvdb | 0:c52ead8719b3 | 809 | if(linenum == 0xFFFF) |
tomvdb | 0:c52ead8719b3 | 810 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 811 | |
tomvdb | 0:c52ead8719b3 | 812 | // Find the length of what is left, including the (yet-to-be-populated) line header |
tomvdb | 0:c52ead8719b3 | 813 | linelen = 0; |
tomvdb | 0:c52ead8719b3 | 814 | while(txtpos[linelen] != NL) |
tomvdb | 0:c52ead8719b3 | 815 | linelen++; |
tomvdb | 0:c52ead8719b3 | 816 | linelen++; // Include the NL in the line length |
tomvdb | 0:c52ead8719b3 | 817 | linelen += sizeof(unsigned short)+sizeof(char); // Add space for the line number and line length |
tomvdb | 0:c52ead8719b3 | 818 | |
tomvdb | 0:c52ead8719b3 | 819 | // Now we have the number, add the line header. |
tomvdb | 0:c52ead8719b3 | 820 | txtpos -= 3; |
tomvdb | 0:c52ead8719b3 | 821 | *((unsigned short *)txtpos) = linenum; |
tomvdb | 0:c52ead8719b3 | 822 | txtpos[sizeof(LINENUM)] = linelen; |
tomvdb | 0:c52ead8719b3 | 823 | |
tomvdb | 0:c52ead8719b3 | 824 | |
tomvdb | 0:c52ead8719b3 | 825 | // Merge it into the rest of the program |
tomvdb | 0:c52ead8719b3 | 826 | start = findline(); |
tomvdb | 0:c52ead8719b3 | 827 | |
tomvdb | 0:c52ead8719b3 | 828 | // If a line with that number exists, then remove it |
tomvdb | 0:c52ead8719b3 | 829 | if(start != program_end && *((LINENUM *)start) == linenum) |
tomvdb | 0:c52ead8719b3 | 830 | { |
tomvdb | 0:c52ead8719b3 | 831 | unsigned char *dest, *from; |
tomvdb | 0:c52ead8719b3 | 832 | unsigned tomove; |
tomvdb | 0:c52ead8719b3 | 833 | |
tomvdb | 0:c52ead8719b3 | 834 | from = start + start[sizeof(LINENUM)]; |
tomvdb | 0:c52ead8719b3 | 835 | dest = start; |
tomvdb | 0:c52ead8719b3 | 836 | |
tomvdb | 0:c52ead8719b3 | 837 | tomove = program_end - from; |
tomvdb | 0:c52ead8719b3 | 838 | while( tomove > 0) |
tomvdb | 0:c52ead8719b3 | 839 | { |
tomvdb | 0:c52ead8719b3 | 840 | *dest = *from; |
tomvdb | 0:c52ead8719b3 | 841 | from++; |
tomvdb | 0:c52ead8719b3 | 842 | dest++; |
tomvdb | 0:c52ead8719b3 | 843 | tomove--; |
tomvdb | 0:c52ead8719b3 | 844 | } |
tomvdb | 0:c52ead8719b3 | 845 | program_end = dest; |
tomvdb | 0:c52ead8719b3 | 846 | } |
tomvdb | 0:c52ead8719b3 | 847 | |
tomvdb | 0:c52ead8719b3 | 848 | if(txtpos[sizeof(LINENUM)+sizeof(char)] == NL) // If the line has no txt, it was just a delete |
tomvdb | 0:c52ead8719b3 | 849 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 850 | |
tomvdb | 0:c52ead8719b3 | 851 | |
tomvdb | 0:c52ead8719b3 | 852 | |
tomvdb | 0:c52ead8719b3 | 853 | // Make room for the new line, either all in one hit or lots of little shuffles |
tomvdb | 0:c52ead8719b3 | 854 | while(linelen > 0) |
tomvdb | 0:c52ead8719b3 | 855 | { |
tomvdb | 0:c52ead8719b3 | 856 | unsigned int tomove; |
tomvdb | 0:c52ead8719b3 | 857 | unsigned char *from,*dest; |
tomvdb | 0:c52ead8719b3 | 858 | unsigned int space_to_make; |
tomvdb | 0:c52ead8719b3 | 859 | |
tomvdb | 0:c52ead8719b3 | 860 | space_to_make = txtpos - program_end; |
tomvdb | 0:c52ead8719b3 | 861 | |
tomvdb | 0:c52ead8719b3 | 862 | if(space_to_make > linelen) |
tomvdb | 0:c52ead8719b3 | 863 | space_to_make = linelen; |
tomvdb | 0:c52ead8719b3 | 864 | newEnd = program_end+space_to_make; |
tomvdb | 0:c52ead8719b3 | 865 | tomove = program_end - start; |
tomvdb | 0:c52ead8719b3 | 866 | |
tomvdb | 0:c52ead8719b3 | 867 | |
tomvdb | 0:c52ead8719b3 | 868 | // Source and destination - as these areas may overlap we need to move bottom up |
tomvdb | 0:c52ead8719b3 | 869 | from = program_end; |
tomvdb | 0:c52ead8719b3 | 870 | dest = newEnd; |
tomvdb | 0:c52ead8719b3 | 871 | while(tomove > 0) |
tomvdb | 0:c52ead8719b3 | 872 | { |
tomvdb | 0:c52ead8719b3 | 873 | from--; |
tomvdb | 0:c52ead8719b3 | 874 | dest--; |
tomvdb | 0:c52ead8719b3 | 875 | *dest = *from; |
tomvdb | 0:c52ead8719b3 | 876 | tomove--; |
tomvdb | 0:c52ead8719b3 | 877 | } |
tomvdb | 0:c52ead8719b3 | 878 | |
tomvdb | 0:c52ead8719b3 | 879 | // Copy over the bytes into the new space |
tomvdb | 0:c52ead8719b3 | 880 | for(tomove = 0; tomove < space_to_make; tomove++) |
tomvdb | 0:c52ead8719b3 | 881 | { |
tomvdb | 0:c52ead8719b3 | 882 | *start = *txtpos; |
tomvdb | 0:c52ead8719b3 | 883 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 884 | start++; |
tomvdb | 0:c52ead8719b3 | 885 | linelen--; |
tomvdb | 0:c52ead8719b3 | 886 | } |
tomvdb | 0:c52ead8719b3 | 887 | program_end = newEnd; |
tomvdb | 0:c52ead8719b3 | 888 | } |
tomvdb | 0:c52ead8719b3 | 889 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 890 | |
tomvdb | 0:c52ead8719b3 | 891 | unimplemented: |
tomvdb | 0:c52ead8719b3 | 892 | printmsg(unimplimentedmsg); |
tomvdb | 0:c52ead8719b3 | 893 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 894 | |
tomvdb | 0:c52ead8719b3 | 895 | qhow: |
tomvdb | 0:c52ead8719b3 | 896 | printmsg(howmsg); |
tomvdb | 0:c52ead8719b3 | 897 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 898 | |
tomvdb | 0:c52ead8719b3 | 899 | qwhat: |
tomvdb | 0:c52ead8719b3 | 900 | printmsgNoNL(whatmsg); |
tomvdb | 0:c52ead8719b3 | 901 | if(current_line != NULL) |
tomvdb | 0:c52ead8719b3 | 902 | { |
tomvdb | 0:c52ead8719b3 | 903 | unsigned char tmp = *txtpos; |
tomvdb | 0:c52ead8719b3 | 904 | if(*txtpos != NL) |
tomvdb | 0:c52ead8719b3 | 905 | *txtpos = '^'; |
tomvdb | 0:c52ead8719b3 | 906 | list_line = current_line; |
tomvdb | 0:c52ead8719b3 | 907 | printline(); |
tomvdb | 0:c52ead8719b3 | 908 | *txtpos = tmp; |
tomvdb | 0:c52ead8719b3 | 909 | } |
tomvdb | 0:c52ead8719b3 | 910 | line_terminator(); |
tomvdb | 0:c52ead8719b3 | 911 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 912 | |
tomvdb | 0:c52ead8719b3 | 913 | qsorry: |
tomvdb | 0:c52ead8719b3 | 914 | printmsg(sorrymsg); |
tomvdb | 0:c52ead8719b3 | 915 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 916 | |
tomvdb | 0:c52ead8719b3 | 917 | run_next_statement: |
tomvdb | 0:c52ead8719b3 | 918 | while(*txtpos == ':') |
tomvdb | 0:c52ead8719b3 | 919 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 920 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 921 | if(*txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 922 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 923 | goto interperateAtTxtpos; |
tomvdb | 0:c52ead8719b3 | 924 | |
tomvdb | 0:c52ead8719b3 | 925 | direct: |
tomvdb | 0:c52ead8719b3 | 926 | txtpos = program_end+sizeof(LINENUM); |
tomvdb | 0:c52ead8719b3 | 927 | if(*txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 928 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 929 | |
tomvdb | 0:c52ead8719b3 | 930 | interperateAtTxtpos: |
tomvdb | 0:c52ead8719b3 | 931 | if(breakcheck()) |
tomvdb | 0:c52ead8719b3 | 932 | { |
tomvdb | 0:c52ead8719b3 | 933 | printmsg(breakmsg); |
tomvdb | 0:c52ead8719b3 | 934 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 935 | } |
tomvdb | 0:c52ead8719b3 | 936 | |
tomvdb | 0:c52ead8719b3 | 937 | scantable(keywords); |
tomvdb | 0:c52ead8719b3 | 938 | |
tomvdb | 0:c52ead8719b3 | 939 | switch(table_index) |
tomvdb | 0:c52ead8719b3 | 940 | { |
tomvdb | 0:c52ead8719b3 | 941 | case KW_DELAY: |
tomvdb | 0:c52ead8719b3 | 942 | { |
tomvdb | 0:c52ead8719b3 | 943 | |
tomvdb | 0:c52ead8719b3 | 944 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 945 | val = expression(); |
tomvdb | 0:c52ead8719b3 | 946 | wait_ms( val ); |
tomvdb | 0:c52ead8719b3 | 947 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 948 | } |
tomvdb | 0:c52ead8719b3 | 949 | |
tomvdb | 0:c52ead8719b3 | 950 | case KW_FILES: |
tomvdb | 0:c52ead8719b3 | 951 | goto files; |
tomvdb | 0:c52ead8719b3 | 952 | case KW_LIST: |
tomvdb | 0:c52ead8719b3 | 953 | goto list; |
tomvdb | 0:c52ead8719b3 | 954 | case KW_CHAIN: |
tomvdb | 0:c52ead8719b3 | 955 | goto chain; |
tomvdb | 0:c52ead8719b3 | 956 | case KW_LOAD: |
tomvdb | 0:c52ead8719b3 | 957 | goto load; |
tomvdb | 0:c52ead8719b3 | 958 | case KW_MEM: |
tomvdb | 0:c52ead8719b3 | 959 | goto mem; |
tomvdb | 0:c52ead8719b3 | 960 | case KW_NEW: |
tomvdb | 0:c52ead8719b3 | 961 | if(txtpos[0] != NL) |
tomvdb | 0:c52ead8719b3 | 962 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 963 | program_end = program_start; |
tomvdb | 0:c52ead8719b3 | 964 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 965 | case KW_RUN: |
tomvdb | 0:c52ead8719b3 | 966 | current_line = program_start; |
tomvdb | 0:c52ead8719b3 | 967 | goto execline; |
tomvdb | 0:c52ead8719b3 | 968 | case KW_SAVE: |
tomvdb | 0:c52ead8719b3 | 969 | goto save; |
tomvdb | 0:c52ead8719b3 | 970 | case KW_NEXT: |
tomvdb | 0:c52ead8719b3 | 971 | goto next; |
tomvdb | 0:c52ead8719b3 | 972 | case KW_LET: |
tomvdb | 0:c52ead8719b3 | 973 | goto assignment; |
tomvdb | 0:c52ead8719b3 | 974 | case KW_IF: |
tomvdb | 0:c52ead8719b3 | 975 | short int val; |
tomvdb | 0:c52ead8719b3 | 976 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 977 | val = expression(); |
tomvdb | 0:c52ead8719b3 | 978 | if(expression_error || *txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 979 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 980 | if(val != 0) |
tomvdb | 0:c52ead8719b3 | 981 | goto interperateAtTxtpos; |
tomvdb | 0:c52ead8719b3 | 982 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 983 | |
tomvdb | 0:c52ead8719b3 | 984 | case KW_GOTO: |
tomvdb | 0:c52ead8719b3 | 985 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 986 | linenum = expression(); |
tomvdb | 0:c52ead8719b3 | 987 | if(expression_error || *txtpos != NL) |
tomvdb | 0:c52ead8719b3 | 988 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 989 | current_line = findline(); |
tomvdb | 0:c52ead8719b3 | 990 | goto execline; |
tomvdb | 0:c52ead8719b3 | 991 | |
tomvdb | 0:c52ead8719b3 | 992 | case KW_GOSUB: |
tomvdb | 0:c52ead8719b3 | 993 | goto gosub; |
tomvdb | 0:c52ead8719b3 | 994 | case KW_RETURN: |
tomvdb | 0:c52ead8719b3 | 995 | goto gosub_return; |
tomvdb | 0:c52ead8719b3 | 996 | case KW_REM: |
tomvdb | 0:c52ead8719b3 | 997 | case KW_QUOTE: |
tomvdb | 0:c52ead8719b3 | 998 | goto execnextline; // Ignore line completely |
tomvdb | 0:c52ead8719b3 | 999 | case KW_FOR: |
tomvdb | 0:c52ead8719b3 | 1000 | goto forloop; |
tomvdb | 0:c52ead8719b3 | 1001 | case KW_INPUT: |
tomvdb | 0:c52ead8719b3 | 1002 | goto input; |
tomvdb | 0:c52ead8719b3 | 1003 | case KW_PRINT: |
tomvdb | 0:c52ead8719b3 | 1004 | case KW_QMARK: |
tomvdb | 0:c52ead8719b3 | 1005 | goto print; |
tomvdb | 0:c52ead8719b3 | 1006 | case KW_POKE: |
tomvdb | 0:c52ead8719b3 | 1007 | goto poke; |
tomvdb | 0:c52ead8719b3 | 1008 | case KW_END: |
tomvdb | 0:c52ead8719b3 | 1009 | case KW_STOP: |
tomvdb | 0:c52ead8719b3 | 1010 | // This is the easy way to end - set the current line to the end of program attempt to run it |
tomvdb | 0:c52ead8719b3 | 1011 | if(txtpos[0] != NL) |
tomvdb | 0:c52ead8719b3 | 1012 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1013 | current_line = program_end; |
tomvdb | 0:c52ead8719b3 | 1014 | goto execline; |
tomvdb | 0:c52ead8719b3 | 1015 | case KW_BYE: |
tomvdb | 0:c52ead8719b3 | 1016 | // Leave the basic interperater |
tomvdb | 0:c52ead8719b3 | 1017 | return; |
tomvdb | 0:c52ead8719b3 | 1018 | |
tomvdb | 0:c52ead8719b3 | 1019 | case KW_AWRITE: // AWRITE <pin>, HIGH|LOW |
tomvdb | 0:c52ead8719b3 | 1020 | isDigital = false; |
tomvdb | 0:c52ead8719b3 | 1021 | goto awrite; |
tomvdb | 0:c52ead8719b3 | 1022 | case KW_DWRITE: // DWRITE <pin>, HIGH|LOW |
tomvdb | 0:c52ead8719b3 | 1023 | isDigital = true; |
tomvdb | 0:c52ead8719b3 | 1024 | goto dwrite; |
tomvdb | 0:c52ead8719b3 | 1025 | |
tomvdb | 0:c52ead8719b3 | 1026 | case KW_RSEED: |
tomvdb | 0:c52ead8719b3 | 1027 | goto rseed; |
tomvdb | 0:c52ead8719b3 | 1028 | |
tomvdb | 0:c52ead8719b3 | 1029 | #ifdef ENABLE_TONES |
tomvdb | 0:c52ead8719b3 | 1030 | case KW_TONEW: |
tomvdb | 0:c52ead8719b3 | 1031 | alsoWait = true; |
tomvdb | 0:c52ead8719b3 | 1032 | case KW_TONE: |
tomvdb | 0:c52ead8719b3 | 1033 | goto tonegen; |
tomvdb | 0:c52ead8719b3 | 1034 | case KW_NOTONE: |
tomvdb | 0:c52ead8719b3 | 1035 | goto tonestop; |
tomvdb | 0:c52ead8719b3 | 1036 | #endif |
tomvdb | 0:c52ead8719b3 | 1037 | |
tomvdb | 0:c52ead8719b3 | 1038 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 1039 | case KW_EFORMAT: |
tomvdb | 0:c52ead8719b3 | 1040 | goto eformat; |
tomvdb | 0:c52ead8719b3 | 1041 | case KW_ESAVE: |
tomvdb | 0:c52ead8719b3 | 1042 | goto esave; |
tomvdb | 0:c52ead8719b3 | 1043 | case KW_ELOAD: |
tomvdb | 0:c52ead8719b3 | 1044 | goto eload; |
tomvdb | 0:c52ead8719b3 | 1045 | case KW_ELIST: |
tomvdb | 0:c52ead8719b3 | 1046 | goto elist; |
tomvdb | 0:c52ead8719b3 | 1047 | case KW_ECHAIN: |
tomvdb | 0:c52ead8719b3 | 1048 | goto echain; |
tomvdb | 0:c52ead8719b3 | 1049 | #endif |
tomvdb | 0:c52ead8719b3 | 1050 | |
tomvdb | 0:c52ead8719b3 | 1051 | case KW_DEFAULT: |
tomvdb | 0:c52ead8719b3 | 1052 | goto assignment; |
tomvdb | 0:c52ead8719b3 | 1053 | default: |
tomvdb | 0:c52ead8719b3 | 1054 | break; |
tomvdb | 0:c52ead8719b3 | 1055 | } |
tomvdb | 0:c52ead8719b3 | 1056 | |
tomvdb | 0:c52ead8719b3 | 1057 | execnextline: |
tomvdb | 0:c52ead8719b3 | 1058 | if(current_line == NULL) // Processing direct commands? |
tomvdb | 0:c52ead8719b3 | 1059 | goto prompt; |
tomvdb | 0:c52ead8719b3 | 1060 | current_line += current_line[sizeof(LINENUM)]; |
tomvdb | 0:c52ead8719b3 | 1061 | |
tomvdb | 0:c52ead8719b3 | 1062 | execline: |
tomvdb | 0:c52ead8719b3 | 1063 | if(current_line == program_end) // Out of lines to run |
tomvdb | 0:c52ead8719b3 | 1064 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1065 | txtpos = current_line+sizeof(LINENUM)+sizeof(char); |
tomvdb | 0:c52ead8719b3 | 1066 | goto interperateAtTxtpos; |
tomvdb | 0:c52ead8719b3 | 1067 | |
tomvdb | 0:c52ead8719b3 | 1068 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 1069 | elist: |
tomvdb | 0:c52ead8719b3 | 1070 | { |
tomvdb | 0:c52ead8719b3 | 1071 | int i; |
tomvdb | 0:c52ead8719b3 | 1072 | for( i = 0 ; i < (E2END +1) ; i++ ) |
tomvdb | 0:c52ead8719b3 | 1073 | { |
tomvdb | 0:c52ead8719b3 | 1074 | val = EEPROM.read( i ); |
tomvdb | 0:c52ead8719b3 | 1075 | |
tomvdb | 0:c52ead8719b3 | 1076 | if( val == '\0' ) { |
tomvdb | 0:c52ead8719b3 | 1077 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 1078 | } |
tomvdb | 0:c52ead8719b3 | 1079 | |
tomvdb | 0:c52ead8719b3 | 1080 | if( ((val < ' ') || (val > '~')) && (val != NL) && (val != CR)) { |
tomvdb | 0:c52ead8719b3 | 1081 | outchar( '?' ); |
tomvdb | 0:c52ead8719b3 | 1082 | } |
tomvdb | 0:c52ead8719b3 | 1083 | else { |
tomvdb | 0:c52ead8719b3 | 1084 | outchar( val ); |
tomvdb | 0:c52ead8719b3 | 1085 | } |
tomvdb | 0:c52ead8719b3 | 1086 | } |
tomvdb | 0:c52ead8719b3 | 1087 | } |
tomvdb | 0:c52ead8719b3 | 1088 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 1089 | |
tomvdb | 0:c52ead8719b3 | 1090 | eformat: |
tomvdb | 0:c52ead8719b3 | 1091 | { |
tomvdb | 0:c52ead8719b3 | 1092 | for( int i = 0 ; i < E2END ; i++ ) |
tomvdb | 0:c52ead8719b3 | 1093 | { |
tomvdb | 0:c52ead8719b3 | 1094 | if( (i & 0x03f) == 0x20 ) outchar( '.' ); |
tomvdb | 0:c52ead8719b3 | 1095 | EEPROM.write( i, 0 ); |
tomvdb | 0:c52ead8719b3 | 1096 | } |
tomvdb | 0:c52ead8719b3 | 1097 | outchar( LF ); |
tomvdb | 0:c52ead8719b3 | 1098 | } |
tomvdb | 0:c52ead8719b3 | 1099 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 1100 | |
tomvdb | 0:c52ead8719b3 | 1101 | esave: |
tomvdb | 0:c52ead8719b3 | 1102 | { |
tomvdb | 0:c52ead8719b3 | 1103 | outStream = kStreamEEProm; |
tomvdb | 0:c52ead8719b3 | 1104 | eepos = 0; |
tomvdb | 0:c52ead8719b3 | 1105 | |
tomvdb | 0:c52ead8719b3 | 1106 | // copied from "List" |
tomvdb | 0:c52ead8719b3 | 1107 | list_line = findline(); |
tomvdb | 0:c52ead8719b3 | 1108 | while(list_line != program_end) |
tomvdb | 0:c52ead8719b3 | 1109 | printline(); |
tomvdb | 0:c52ead8719b3 | 1110 | |
tomvdb | 0:c52ead8719b3 | 1111 | // go back to standard output, close the file |
tomvdb | 0:c52ead8719b3 | 1112 | outStream = kStreamSerial; |
tomvdb | 0:c52ead8719b3 | 1113 | |
tomvdb | 0:c52ead8719b3 | 1114 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1115 | } |
tomvdb | 0:c52ead8719b3 | 1116 | |
tomvdb | 0:c52ead8719b3 | 1117 | |
tomvdb | 0:c52ead8719b3 | 1118 | echain: |
tomvdb | 0:c52ead8719b3 | 1119 | runAfterLoad = true; |
tomvdb | 0:c52ead8719b3 | 1120 | |
tomvdb | 0:c52ead8719b3 | 1121 | eload: |
tomvdb | 0:c52ead8719b3 | 1122 | // clear the program |
tomvdb | 0:c52ead8719b3 | 1123 | program_end = program_start; |
tomvdb | 0:c52ead8719b3 | 1124 | |
tomvdb | 0:c52ead8719b3 | 1125 | // load from a file into memory |
tomvdb | 0:c52ead8719b3 | 1126 | eepos = 0; |
tomvdb | 0:c52ead8719b3 | 1127 | inStream = kStreamEEProm; |
tomvdb | 0:c52ead8719b3 | 1128 | inhibitOutput = true; |
tomvdb | 0:c52ead8719b3 | 1129 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1130 | #endif /* ENABLE_EEPROM */ |
tomvdb | 0:c52ead8719b3 | 1131 | |
tomvdb | 0:c52ead8719b3 | 1132 | input: |
tomvdb | 0:c52ead8719b3 | 1133 | { |
tomvdb | 0:c52ead8719b3 | 1134 | unsigned char var; |
tomvdb | 0:c52ead8719b3 | 1135 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1136 | if(*txtpos < 'A' || *txtpos > 'Z') |
tomvdb | 0:c52ead8719b3 | 1137 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1138 | var = *txtpos; |
tomvdb | 0:c52ead8719b3 | 1139 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1140 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1141 | if(*txtpos != NL && *txtpos != ':') |
tomvdb | 0:c52ead8719b3 | 1142 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1143 | ((short int *)variables_begin)[var-'A'] = 99; |
tomvdb | 0:c52ead8719b3 | 1144 | |
tomvdb | 0:c52ead8719b3 | 1145 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1146 | } |
tomvdb | 0:c52ead8719b3 | 1147 | |
tomvdb | 0:c52ead8719b3 | 1148 | forloop: |
tomvdb | 0:c52ead8719b3 | 1149 | { |
tomvdb | 0:c52ead8719b3 | 1150 | unsigned char var; |
tomvdb | 0:c52ead8719b3 | 1151 | short int initial, step, terminal; |
tomvdb | 0:c52ead8719b3 | 1152 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1153 | if(*txtpos < 'A' || *txtpos > 'Z') |
tomvdb | 0:c52ead8719b3 | 1154 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1155 | var = *txtpos; |
tomvdb | 0:c52ead8719b3 | 1156 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1157 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1158 | if(*txtpos != '=') |
tomvdb | 0:c52ead8719b3 | 1159 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1160 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1161 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1162 | |
tomvdb | 0:c52ead8719b3 | 1163 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1164 | initial = expression(); |
tomvdb | 0:c52ead8719b3 | 1165 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1166 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1167 | |
tomvdb | 0:c52ead8719b3 | 1168 | scantable(to_tab); |
tomvdb | 0:c52ead8719b3 | 1169 | if(table_index != 0) |
tomvdb | 0:c52ead8719b3 | 1170 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1171 | |
tomvdb | 0:c52ead8719b3 | 1172 | terminal = expression(); |
tomvdb | 0:c52ead8719b3 | 1173 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1174 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1175 | |
tomvdb | 0:c52ead8719b3 | 1176 | scantable(step_tab); |
tomvdb | 0:c52ead8719b3 | 1177 | if(table_index == 0) |
tomvdb | 0:c52ead8719b3 | 1178 | { |
tomvdb | 0:c52ead8719b3 | 1179 | step = expression(); |
tomvdb | 0:c52ead8719b3 | 1180 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1181 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1182 | } |
tomvdb | 0:c52ead8719b3 | 1183 | else |
tomvdb | 0:c52ead8719b3 | 1184 | step = 1; |
tomvdb | 0:c52ead8719b3 | 1185 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1186 | if(*txtpos != NL && *txtpos != ':') |
tomvdb | 0:c52ead8719b3 | 1187 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1188 | |
tomvdb | 0:c52ead8719b3 | 1189 | |
tomvdb | 0:c52ead8719b3 | 1190 | if(!expression_error && *txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 1191 | { |
tomvdb | 0:c52ead8719b3 | 1192 | struct stack_for_frame *f; |
tomvdb | 0:c52ead8719b3 | 1193 | if(sp + sizeof(struct stack_for_frame) < stack_limit) |
tomvdb | 0:c52ead8719b3 | 1194 | goto qsorry; |
tomvdb | 0:c52ead8719b3 | 1195 | |
tomvdb | 0:c52ead8719b3 | 1196 | sp -= sizeof(struct stack_for_frame); |
tomvdb | 0:c52ead8719b3 | 1197 | f = (struct stack_for_frame *)sp; |
tomvdb | 0:c52ead8719b3 | 1198 | ((short int *)variables_begin)[var-'A'] = initial; |
tomvdb | 0:c52ead8719b3 | 1199 | f->frame_type = STACK_FOR_FLAG; |
tomvdb | 0:c52ead8719b3 | 1200 | f->for_var = var; |
tomvdb | 0:c52ead8719b3 | 1201 | f->terminal = terminal; |
tomvdb | 0:c52ead8719b3 | 1202 | f->step = step; |
tomvdb | 0:c52ead8719b3 | 1203 | f->txtpos = txtpos; |
tomvdb | 0:c52ead8719b3 | 1204 | f->current_line = current_line; |
tomvdb | 0:c52ead8719b3 | 1205 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1206 | } |
tomvdb | 0:c52ead8719b3 | 1207 | } |
tomvdb | 0:c52ead8719b3 | 1208 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 1209 | |
tomvdb | 0:c52ead8719b3 | 1210 | gosub: |
tomvdb | 0:c52ead8719b3 | 1211 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1212 | linenum = expression(); |
tomvdb | 0:c52ead8719b3 | 1213 | if(!expression_error && *txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 1214 | { |
tomvdb | 0:c52ead8719b3 | 1215 | struct stack_gosub_frame *f; |
tomvdb | 0:c52ead8719b3 | 1216 | if(sp + sizeof(struct stack_gosub_frame) < stack_limit) |
tomvdb | 0:c52ead8719b3 | 1217 | goto qsorry; |
tomvdb | 0:c52ead8719b3 | 1218 | |
tomvdb | 0:c52ead8719b3 | 1219 | sp -= sizeof(struct stack_gosub_frame); |
tomvdb | 0:c52ead8719b3 | 1220 | f = (struct stack_gosub_frame *)sp; |
tomvdb | 0:c52ead8719b3 | 1221 | f->frame_type = STACK_GOSUB_FLAG; |
tomvdb | 0:c52ead8719b3 | 1222 | f->txtpos = txtpos; |
tomvdb | 0:c52ead8719b3 | 1223 | f->current_line = current_line; |
tomvdb | 0:c52ead8719b3 | 1224 | current_line = findline(); |
tomvdb | 0:c52ead8719b3 | 1225 | goto execline; |
tomvdb | 0:c52ead8719b3 | 1226 | } |
tomvdb | 0:c52ead8719b3 | 1227 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 1228 | |
tomvdb | 0:c52ead8719b3 | 1229 | next: |
tomvdb | 0:c52ead8719b3 | 1230 | // Fnd the variable name |
tomvdb | 0:c52ead8719b3 | 1231 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1232 | if(*txtpos < 'A' || *txtpos > 'Z') |
tomvdb | 0:c52ead8719b3 | 1233 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 1234 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1235 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1236 | if(*txtpos != ':' && *txtpos != NL) |
tomvdb | 0:c52ead8719b3 | 1237 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1238 | |
tomvdb | 0:c52ead8719b3 | 1239 | gosub_return: |
tomvdb | 0:c52ead8719b3 | 1240 | // Now walk up the stack frames and find the frame we want, if present |
tomvdb | 0:c52ead8719b3 | 1241 | tempsp = sp; |
tomvdb | 0:c52ead8719b3 | 1242 | while(tempsp < program+sizeof(program)-1) |
tomvdb | 0:c52ead8719b3 | 1243 | { |
tomvdb | 0:c52ead8719b3 | 1244 | switch(tempsp[0]) |
tomvdb | 0:c52ead8719b3 | 1245 | { |
tomvdb | 0:c52ead8719b3 | 1246 | case STACK_GOSUB_FLAG: |
tomvdb | 0:c52ead8719b3 | 1247 | if(table_index == KW_RETURN) |
tomvdb | 0:c52ead8719b3 | 1248 | { |
tomvdb | 0:c52ead8719b3 | 1249 | struct stack_gosub_frame *f = (struct stack_gosub_frame *)tempsp; |
tomvdb | 0:c52ead8719b3 | 1250 | current_line = f->current_line; |
tomvdb | 0:c52ead8719b3 | 1251 | txtpos = f->txtpos; |
tomvdb | 0:c52ead8719b3 | 1252 | sp += sizeof(struct stack_gosub_frame); |
tomvdb | 0:c52ead8719b3 | 1253 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1254 | } |
tomvdb | 0:c52ead8719b3 | 1255 | // This is not the loop you are looking for... so Walk back up the stack |
tomvdb | 0:c52ead8719b3 | 1256 | tempsp += sizeof(struct stack_gosub_frame); |
tomvdb | 0:c52ead8719b3 | 1257 | break; |
tomvdb | 0:c52ead8719b3 | 1258 | case STACK_FOR_FLAG: |
tomvdb | 0:c52ead8719b3 | 1259 | // Flag, Var, Final, Step |
tomvdb | 0:c52ead8719b3 | 1260 | if(table_index == KW_NEXT) |
tomvdb | 0:c52ead8719b3 | 1261 | { |
tomvdb | 0:c52ead8719b3 | 1262 | struct stack_for_frame *f = (struct stack_for_frame *)tempsp; |
tomvdb | 0:c52ead8719b3 | 1263 | // Is the the variable we are looking for? |
tomvdb | 0:c52ead8719b3 | 1264 | if(txtpos[-1] == f->for_var) |
tomvdb | 0:c52ead8719b3 | 1265 | { |
tomvdb | 0:c52ead8719b3 | 1266 | short int *varaddr = ((short int *)variables_begin) + txtpos[-1] - 'A'; |
tomvdb | 0:c52ead8719b3 | 1267 | *varaddr = *varaddr + f->step; |
tomvdb | 0:c52ead8719b3 | 1268 | // Use a different test depending on the sign of the step increment |
tomvdb | 0:c52ead8719b3 | 1269 | if((f->step > 0 && *varaddr <= f->terminal) || (f->step < 0 && *varaddr >= f->terminal)) |
tomvdb | 0:c52ead8719b3 | 1270 | { |
tomvdb | 0:c52ead8719b3 | 1271 | // We have to loop so don't pop the stack |
tomvdb | 0:c52ead8719b3 | 1272 | txtpos = f->txtpos; |
tomvdb | 0:c52ead8719b3 | 1273 | current_line = f->current_line; |
tomvdb | 0:c52ead8719b3 | 1274 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1275 | } |
tomvdb | 0:c52ead8719b3 | 1276 | // We've run to the end of the loop. drop out of the loop, popping the stack |
tomvdb | 0:c52ead8719b3 | 1277 | sp = tempsp + sizeof(struct stack_for_frame); |
tomvdb | 0:c52ead8719b3 | 1278 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1279 | } |
tomvdb | 0:c52ead8719b3 | 1280 | } |
tomvdb | 0:c52ead8719b3 | 1281 | // This is not the loop you are looking for... so Walk back up the stack |
tomvdb | 0:c52ead8719b3 | 1282 | tempsp += sizeof(struct stack_for_frame); |
tomvdb | 0:c52ead8719b3 | 1283 | break; |
tomvdb | 0:c52ead8719b3 | 1284 | default: |
tomvdb | 0:c52ead8719b3 | 1285 | //printf("Stack is stuffed!\n"); |
tomvdb | 0:c52ead8719b3 | 1286 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1287 | } |
tomvdb | 0:c52ead8719b3 | 1288 | } |
tomvdb | 0:c52ead8719b3 | 1289 | // Didn't find the variable we've been looking for |
tomvdb | 0:c52ead8719b3 | 1290 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 1291 | |
tomvdb | 0:c52ead8719b3 | 1292 | assignment: |
tomvdb | 0:c52ead8719b3 | 1293 | { |
tomvdb | 0:c52ead8719b3 | 1294 | short int value; |
tomvdb | 0:c52ead8719b3 | 1295 | short int *var; |
tomvdb | 0:c52ead8719b3 | 1296 | |
tomvdb | 0:c52ead8719b3 | 1297 | if(*txtpos < 'A' || *txtpos > 'Z') |
tomvdb | 0:c52ead8719b3 | 1298 | goto qhow; |
tomvdb | 0:c52ead8719b3 | 1299 | var = (short int *)variables_begin + *txtpos - 'A'; |
tomvdb | 0:c52ead8719b3 | 1300 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1301 | |
tomvdb | 0:c52ead8719b3 | 1302 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1303 | |
tomvdb | 0:c52ead8719b3 | 1304 | if (*txtpos != '=') |
tomvdb | 0:c52ead8719b3 | 1305 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1306 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1307 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1308 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1309 | value = expression(); |
tomvdb | 0:c52ead8719b3 | 1310 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1311 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1312 | // Check that we are at the end of the statement |
tomvdb | 0:c52ead8719b3 | 1313 | if(*txtpos != NL && *txtpos != ':') |
tomvdb | 0:c52ead8719b3 | 1314 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1315 | *var = value; |
tomvdb | 0:c52ead8719b3 | 1316 | } |
tomvdb | 0:c52ead8719b3 | 1317 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1318 | poke: |
tomvdb | 0:c52ead8719b3 | 1319 | { |
tomvdb | 0:c52ead8719b3 | 1320 | short int value; |
tomvdb | 0:c52ead8719b3 | 1321 | unsigned char *address; |
tomvdb | 0:c52ead8719b3 | 1322 | |
tomvdb | 0:c52ead8719b3 | 1323 | // Work out where to put it |
tomvdb | 0:c52ead8719b3 | 1324 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1325 | value = expression(); |
tomvdb | 0:c52ead8719b3 | 1326 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1327 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1328 | address = (unsigned char *)value; |
tomvdb | 0:c52ead8719b3 | 1329 | |
tomvdb | 0:c52ead8719b3 | 1330 | // check for a comma |
tomvdb | 0:c52ead8719b3 | 1331 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1332 | if (*txtpos != ',') |
tomvdb | 0:c52ead8719b3 | 1333 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1334 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1335 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1336 | |
tomvdb | 0:c52ead8719b3 | 1337 | // Now get the value to assign |
tomvdb | 0:c52ead8719b3 | 1338 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1339 | value = expression(); |
tomvdb | 0:c52ead8719b3 | 1340 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1341 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1342 | //printf("Poke %p value %i\n",address, (unsigned char)value); |
tomvdb | 0:c52ead8719b3 | 1343 | // Check that we are at the end of the statement |
tomvdb | 0:c52ead8719b3 | 1344 | if(*txtpos != NL && *txtpos != ':') |
tomvdb | 0:c52ead8719b3 | 1345 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1346 | } |
tomvdb | 0:c52ead8719b3 | 1347 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1348 | |
tomvdb | 0:c52ead8719b3 | 1349 | list: |
tomvdb | 0:c52ead8719b3 | 1350 | linenum = testnum(); // Retuns 0 if no line found. |
tomvdb | 0:c52ead8719b3 | 1351 | |
tomvdb | 0:c52ead8719b3 | 1352 | // Should be EOL |
tomvdb | 0:c52ead8719b3 | 1353 | if(txtpos[0] != NL) |
tomvdb | 0:c52ead8719b3 | 1354 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1355 | |
tomvdb | 0:c52ead8719b3 | 1356 | // Find the line |
tomvdb | 0:c52ead8719b3 | 1357 | list_line = findline(); |
tomvdb | 0:c52ead8719b3 | 1358 | while(list_line != program_end) |
tomvdb | 0:c52ead8719b3 | 1359 | printline(); |
tomvdb | 0:c52ead8719b3 | 1360 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1361 | |
tomvdb | 0:c52ead8719b3 | 1362 | print: |
tomvdb | 0:c52ead8719b3 | 1363 | // If we have an empty list then just put out a NL |
tomvdb | 0:c52ead8719b3 | 1364 | if(*txtpos == ':' ) |
tomvdb | 0:c52ead8719b3 | 1365 | { |
tomvdb | 0:c52ead8719b3 | 1366 | line_terminator(); |
tomvdb | 0:c52ead8719b3 | 1367 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1368 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1369 | } |
tomvdb | 0:c52ead8719b3 | 1370 | if(*txtpos == NL) |
tomvdb | 0:c52ead8719b3 | 1371 | { |
tomvdb | 0:c52ead8719b3 | 1372 | goto execnextline; |
tomvdb | 0:c52ead8719b3 | 1373 | } |
tomvdb | 0:c52ead8719b3 | 1374 | |
tomvdb | 0:c52ead8719b3 | 1375 | while(1) |
tomvdb | 0:c52ead8719b3 | 1376 | { |
tomvdb | 0:c52ead8719b3 | 1377 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1378 | if(print_quoted_string()) |
tomvdb | 0:c52ead8719b3 | 1379 | { |
tomvdb | 0:c52ead8719b3 | 1380 | ; |
tomvdb | 0:c52ead8719b3 | 1381 | } |
tomvdb | 0:c52ead8719b3 | 1382 | else if(*txtpos == '"' || *txtpos == '\'') |
tomvdb | 0:c52ead8719b3 | 1383 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1384 | else |
tomvdb | 0:c52ead8719b3 | 1385 | { |
tomvdb | 0:c52ead8719b3 | 1386 | short int e; |
tomvdb | 0:c52ead8719b3 | 1387 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1388 | e = expression(); |
tomvdb | 0:c52ead8719b3 | 1389 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1390 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1391 | printnum(e); |
tomvdb | 0:c52ead8719b3 | 1392 | } |
tomvdb | 0:c52ead8719b3 | 1393 | |
tomvdb | 0:c52ead8719b3 | 1394 | // At this point we have three options, a comma or a new line |
tomvdb | 0:c52ead8719b3 | 1395 | if(*txtpos == ',') |
tomvdb | 0:c52ead8719b3 | 1396 | txtpos++; // Skip the comma and move onto the next |
tomvdb | 0:c52ead8719b3 | 1397 | else if(txtpos[0] == ';' && (txtpos[1] == NL || txtpos[1] == ':')) |
tomvdb | 0:c52ead8719b3 | 1398 | { |
tomvdb | 0:c52ead8719b3 | 1399 | txtpos++; // This has to be the end of the print - no newline |
tomvdb | 0:c52ead8719b3 | 1400 | break; |
tomvdb | 0:c52ead8719b3 | 1401 | } |
tomvdb | 0:c52ead8719b3 | 1402 | else if(*txtpos == NL || *txtpos == ':') |
tomvdb | 0:c52ead8719b3 | 1403 | { |
tomvdb | 0:c52ead8719b3 | 1404 | line_terminator(); // The end of the print statement |
tomvdb | 0:c52ead8719b3 | 1405 | break; |
tomvdb | 0:c52ead8719b3 | 1406 | } |
tomvdb | 0:c52ead8719b3 | 1407 | else |
tomvdb | 0:c52ead8719b3 | 1408 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1409 | } |
tomvdb | 0:c52ead8719b3 | 1410 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1411 | |
tomvdb | 0:c52ead8719b3 | 1412 | mem: |
tomvdb | 0:c52ead8719b3 | 1413 | // memory free |
tomvdb | 0:c52ead8719b3 | 1414 | printnum(variables_begin-program_end); |
tomvdb | 0:c52ead8719b3 | 1415 | printmsg(memorymsg); |
tomvdb | 0:c52ead8719b3 | 1416 | |
tomvdb | 0:c52ead8719b3 | 1417 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 1418 | { |
tomvdb | 0:c52ead8719b3 | 1419 | // eprom size |
tomvdb | 0:c52ead8719b3 | 1420 | printnum( E2END+1 ); |
tomvdb | 0:c52ead8719b3 | 1421 | printmsg( eeprommsg ); |
tomvdb | 0:c52ead8719b3 | 1422 | |
tomvdb | 0:c52ead8719b3 | 1423 | // figure out the memory usage; |
tomvdb | 0:c52ead8719b3 | 1424 | val = ' '; |
tomvdb | 0:c52ead8719b3 | 1425 | int i; |
tomvdb | 0:c52ead8719b3 | 1426 | for( i=0 ; (i<(E2END+1)) && (val != '\0') ; i++ ) { |
tomvdb | 0:c52ead8719b3 | 1427 | val = EEPROM.read( i ); |
tomvdb | 0:c52ead8719b3 | 1428 | } |
tomvdb | 0:c52ead8719b3 | 1429 | printnum( (E2END +1) - (i-1) ); |
tomvdb | 0:c52ead8719b3 | 1430 | |
tomvdb | 0:c52ead8719b3 | 1431 | printmsg( eepromamsg ); |
tomvdb | 0:c52ead8719b3 | 1432 | } |
tomvdb | 0:c52ead8719b3 | 1433 | #endif /* ENABLE_EEPROM */ |
tomvdb | 0:c52ead8719b3 | 1434 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1435 | |
tomvdb | 0:c52ead8719b3 | 1436 | |
tomvdb | 0:c52ead8719b3 | 1437 | /*************************************************/ |
tomvdb | 0:c52ead8719b3 | 1438 | |
tomvdb | 0:c52ead8719b3 | 1439 | awrite: // AWRITE <pin>,val |
tomvdb | 0:c52ead8719b3 | 1440 | dwrite: |
tomvdb | 0:c52ead8719b3 | 1441 | { |
tomvdb | 0:c52ead8719b3 | 1442 | short int pinNo; |
tomvdb | 0:c52ead8719b3 | 1443 | short int value; |
tomvdb | 0:c52ead8719b3 | 1444 | unsigned char *txtposBak; |
tomvdb | 0:c52ead8719b3 | 1445 | |
tomvdb | 0:c52ead8719b3 | 1446 | // Get the pin number |
tomvdb | 0:c52ead8719b3 | 1447 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1448 | pinNo = expression(); |
tomvdb | 0:c52ead8719b3 | 1449 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1450 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1451 | |
tomvdb | 0:c52ead8719b3 | 1452 | // check for a comma |
tomvdb | 0:c52ead8719b3 | 1453 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1454 | if (*txtpos != ',') |
tomvdb | 0:c52ead8719b3 | 1455 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1456 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1457 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1458 | |
tomvdb | 0:c52ead8719b3 | 1459 | |
tomvdb | 0:c52ead8719b3 | 1460 | txtposBak = txtpos; |
tomvdb | 0:c52ead8719b3 | 1461 | scantable(highlow_tab); |
tomvdb | 0:c52ead8719b3 | 1462 | if(table_index != HIGHLOW_UNKNOWN) |
tomvdb | 0:c52ead8719b3 | 1463 | { |
tomvdb | 0:c52ead8719b3 | 1464 | if( table_index <= HIGHLOW_HIGH ) { |
tomvdb | 0:c52ead8719b3 | 1465 | value = 1; |
tomvdb | 0:c52ead8719b3 | 1466 | } |
tomvdb | 0:c52ead8719b3 | 1467 | else { |
tomvdb | 0:c52ead8719b3 | 1468 | value = 0; |
tomvdb | 0:c52ead8719b3 | 1469 | } |
tomvdb | 0:c52ead8719b3 | 1470 | } |
tomvdb | 0:c52ead8719b3 | 1471 | else { |
tomvdb | 0:c52ead8719b3 | 1472 | |
tomvdb | 0:c52ead8719b3 | 1473 | // and the value (numerical) |
tomvdb | 0:c52ead8719b3 | 1474 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1475 | value = expression(); |
tomvdb | 0:c52ead8719b3 | 1476 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1477 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1478 | } |
tomvdb | 0:c52ead8719b3 | 1479 | /* fix |
tomvdb | 0:c52ead8719b3 | 1480 | pinMode( pinNo, OUTPUT ); |
tomvdb | 0:c52ead8719b3 | 1481 | if( isDigital ) { |
tomvdb | 0:c52ead8719b3 | 1482 | digitalWrite( pinNo, value ); |
tomvdb | 0:c52ead8719b3 | 1483 | } |
tomvdb | 0:c52ead8719b3 | 1484 | else { |
tomvdb | 0:c52ead8719b3 | 1485 | analogWrite( pinNo, value ); |
tomvdb | 0:c52ead8719b3 | 1486 | } |
tomvdb | 0:c52ead8719b3 | 1487 | */ |
tomvdb | 0:c52ead8719b3 | 1488 | } |
tomvdb | 0:c52ead8719b3 | 1489 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1490 | |
tomvdb | 0:c52ead8719b3 | 1491 | /*************************************************/ |
tomvdb | 0:c52ead8719b3 | 1492 | files: |
tomvdb | 0:c52ead8719b3 | 1493 | // display a listing of files on the device. |
tomvdb | 0:c52ead8719b3 | 1494 | // version 1: no support for subdirectories |
tomvdb | 0:c52ead8719b3 | 1495 | |
tomvdb | 0:c52ead8719b3 | 1496 | #ifdef ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1497 | cmd_Files(); |
tomvdb | 0:c52ead8719b3 | 1498 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1499 | #else |
tomvdb | 0:c52ead8719b3 | 1500 | goto unimplemented; |
tomvdb | 0:c52ead8719b3 | 1501 | #endif // ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1502 | |
tomvdb | 0:c52ead8719b3 | 1503 | |
tomvdb | 0:c52ead8719b3 | 1504 | chain: |
tomvdb | 0:c52ead8719b3 | 1505 | runAfterLoad = true; |
tomvdb | 0:c52ead8719b3 | 1506 | |
tomvdb | 0:c52ead8719b3 | 1507 | load: |
tomvdb | 0:c52ead8719b3 | 1508 | // clear the program |
tomvdb | 0:c52ead8719b3 | 1509 | program_end = program_start; |
tomvdb | 0:c52ead8719b3 | 1510 | |
tomvdb | 0:c52ead8719b3 | 1511 | // load from a file into memory |
tomvdb | 0:c52ead8719b3 | 1512 | #ifdef ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1513 | { |
tomvdb | 0:c52ead8719b3 | 1514 | unsigned char *filename; |
tomvdb | 0:c52ead8719b3 | 1515 | |
tomvdb | 0:c52ead8719b3 | 1516 | // Work out the filename |
tomvdb | 0:c52ead8719b3 | 1517 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1518 | filename = filenameWord(); |
tomvdb | 0:c52ead8719b3 | 1519 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1520 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1521 | |
tomvdb | 0:c52ead8719b3 | 1522 | /* |
tomvdb | 0:c52ead8719b3 | 1523 | #ifdef ARDUINO |
tomvdb | 0:c52ead8719b3 | 1524 | // Arduino specific |
tomvdb | 0:c52ead8719b3 | 1525 | if( !SD.exists( (char *)filename )) |
tomvdb | 0:c52ead8719b3 | 1526 | { |
tomvdb | 0:c52ead8719b3 | 1527 | printmsg( sdfilemsg ); |
tomvdb | 0:c52ead8719b3 | 1528 | } |
tomvdb | 0:c52ead8719b3 | 1529 | else { |
tomvdb | 0:c52ead8719b3 | 1530 | |
tomvdb | 0:c52ead8719b3 | 1531 | fp = SD.open( (const char *)filename ); |
tomvdb | 0:c52ead8719b3 | 1532 | inStream = kStreamFile; |
tomvdb | 0:c52ead8719b3 | 1533 | inhibitOutput = true; |
tomvdb | 0:c52ead8719b3 | 1534 | } |
tomvdb | 0:c52ead8719b3 | 1535 | #else // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1536 | // Desktop specific |
tomvdb | 0:c52ead8719b3 | 1537 | #endif // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1538 | */ |
tomvdb | 0:c52ead8719b3 | 1539 | // this will kickstart a series of events to read in from the file. |
tomvdb | 0:c52ead8719b3 | 1540 | |
tomvdb | 0:c52ead8719b3 | 1541 | } |
tomvdb | 0:c52ead8719b3 | 1542 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1543 | #else // ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1544 | goto unimplemented; |
tomvdb | 0:c52ead8719b3 | 1545 | #endif // ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1546 | |
tomvdb | 0:c52ead8719b3 | 1547 | |
tomvdb | 0:c52ead8719b3 | 1548 | |
tomvdb | 0:c52ead8719b3 | 1549 | save: |
tomvdb | 0:c52ead8719b3 | 1550 | // save from memory out to a file |
tomvdb | 0:c52ead8719b3 | 1551 | #ifdef ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1552 | { |
tomvdb | 0:c52ead8719b3 | 1553 | unsigned char *filename; |
tomvdb | 0:c52ead8719b3 | 1554 | |
tomvdb | 0:c52ead8719b3 | 1555 | // Work out the filename |
tomvdb | 0:c52ead8719b3 | 1556 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1557 | filename = filenameWord(); |
tomvdb | 0:c52ead8719b3 | 1558 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1559 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1560 | /* |
tomvdb | 0:c52ead8719b3 | 1561 | #ifdef ARDUINO |
tomvdb | 0:c52ead8719b3 | 1562 | // remove the old file if it exists |
tomvdb | 0:c52ead8719b3 | 1563 | if( SD.exists( (char *)filename )) { |
tomvdb | 0:c52ead8719b3 | 1564 | SD.remove( (char *)filename ); |
tomvdb | 0:c52ead8719b3 | 1565 | } |
tomvdb | 0:c52ead8719b3 | 1566 | |
tomvdb | 0:c52ead8719b3 | 1567 | // open the file, switch over to file output |
tomvdb | 0:c52ead8719b3 | 1568 | fp = SD.open( (const char *)filename, FILE_WRITE ); |
tomvdb | 0:c52ead8719b3 | 1569 | outStream = kStreamFile; |
tomvdb | 0:c52ead8719b3 | 1570 | |
tomvdb | 0:c52ead8719b3 | 1571 | // copied from "List" |
tomvdb | 0:c52ead8719b3 | 1572 | list_line = findline(); |
tomvdb | 0:c52ead8719b3 | 1573 | while(list_line != program_end) |
tomvdb | 0:c52ead8719b3 | 1574 | printline(); |
tomvdb | 0:c52ead8719b3 | 1575 | |
tomvdb | 0:c52ead8719b3 | 1576 | // go back to standard output, close the file |
tomvdb | 0:c52ead8719b3 | 1577 | outStream = kStreamSerial; |
tomvdb | 0:c52ead8719b3 | 1578 | |
tomvdb | 0:c52ead8719b3 | 1579 | fp.close(); |
tomvdb | 0:c52ead8719b3 | 1580 | #else // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1581 | // desktop |
tomvdb | 0:c52ead8719b3 | 1582 | #endif // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1583 | */ |
tomvdb | 0:c52ead8719b3 | 1584 | goto warmstart; |
tomvdb | 0:c52ead8719b3 | 1585 | } |
tomvdb | 0:c52ead8719b3 | 1586 | #else // ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1587 | goto unimplemented; |
tomvdb | 0:c52ead8719b3 | 1588 | #endif // ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1589 | |
tomvdb | 0:c52ead8719b3 | 1590 | rseed: |
tomvdb | 0:c52ead8719b3 | 1591 | { |
tomvdb | 0:c52ead8719b3 | 1592 | short int value; |
tomvdb | 0:c52ead8719b3 | 1593 | |
tomvdb | 0:c52ead8719b3 | 1594 | //Get the pin number |
tomvdb | 0:c52ead8719b3 | 1595 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1596 | value = expression(); |
tomvdb | 0:c52ead8719b3 | 1597 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1598 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1599 | |
tomvdb | 0:c52ead8719b3 | 1600 | |
tomvdb | 0:c52ead8719b3 | 1601 | /* fix |
tomvdb | 0:c52ead8719b3 | 1602 | #ifdef ARDUINO |
tomvdb | 0:c52ead8719b3 | 1603 | randomSeed( value ); |
tomvdb | 0:c52ead8719b3 | 1604 | #else // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1605 | srand( value ); |
tomvdb | 0:c52ead8719b3 | 1606 | #endif // ARDUINO |
tomvdb | 0:c52ead8719b3 | 1607 | */ |
tomvdb | 0:c52ead8719b3 | 1608 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1609 | } |
tomvdb | 0:c52ead8719b3 | 1610 | |
tomvdb | 0:c52ead8719b3 | 1611 | #ifdef ENABLE_TONES |
tomvdb | 0:c52ead8719b3 | 1612 | tonestop: |
tomvdb | 0:c52ead8719b3 | 1613 | noTone( kPiezoPin ); |
tomvdb | 0:c52ead8719b3 | 1614 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1615 | |
tomvdb | 0:c52ead8719b3 | 1616 | tonegen: |
tomvdb | 0:c52ead8719b3 | 1617 | { |
tomvdb | 0:c52ead8719b3 | 1618 | // TONE freq, duration |
tomvdb | 0:c52ead8719b3 | 1619 | // if either are 0, tones turned off |
tomvdb | 0:c52ead8719b3 | 1620 | short int freq; |
tomvdb | 0:c52ead8719b3 | 1621 | short int duration; |
tomvdb | 0:c52ead8719b3 | 1622 | |
tomvdb | 0:c52ead8719b3 | 1623 | //Get the frequency |
tomvdb | 0:c52ead8719b3 | 1624 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1625 | freq = expression(); |
tomvdb | 0:c52ead8719b3 | 1626 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1627 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1628 | |
tomvdb | 0:c52ead8719b3 | 1629 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1630 | if (*txtpos != ',') |
tomvdb | 0:c52ead8719b3 | 1631 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1632 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1633 | ignore_blanks(); |
tomvdb | 0:c52ead8719b3 | 1634 | |
tomvdb | 0:c52ead8719b3 | 1635 | |
tomvdb | 0:c52ead8719b3 | 1636 | //Get the duration |
tomvdb | 0:c52ead8719b3 | 1637 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1638 | duration = expression(); |
tomvdb | 0:c52ead8719b3 | 1639 | if(expression_error) |
tomvdb | 0:c52ead8719b3 | 1640 | goto qwhat; |
tomvdb | 0:c52ead8719b3 | 1641 | |
tomvdb | 0:c52ead8719b3 | 1642 | if( freq == 0 || duration == 0 ) |
tomvdb | 0:c52ead8719b3 | 1643 | goto tonestop; |
tomvdb | 0:c52ead8719b3 | 1644 | |
tomvdb | 0:c52ead8719b3 | 1645 | tone( kPiezoPin, freq, duration ); |
tomvdb | 0:c52ead8719b3 | 1646 | if( alsoWait ) { |
tomvdb | 0:c52ead8719b3 | 1647 | delay( duration ); |
tomvdb | 0:c52ead8719b3 | 1648 | alsoWait = false; |
tomvdb | 0:c52ead8719b3 | 1649 | } |
tomvdb | 0:c52ead8719b3 | 1650 | goto run_next_statement; |
tomvdb | 0:c52ead8719b3 | 1651 | } |
tomvdb | 0:c52ead8719b3 | 1652 | #endif /* ENABLE_TONES */ |
tomvdb | 0:c52ead8719b3 | 1653 | } |
tomvdb | 0:c52ead8719b3 | 1654 | |
tomvdb | 0:c52ead8719b3 | 1655 | // returns 1 if the character is valid in a filename |
tomvdb | 0:c52ead8719b3 | 1656 | static int isValidFnChar( char c ) |
tomvdb | 0:c52ead8719b3 | 1657 | { |
tomvdb | 0:c52ead8719b3 | 1658 | if( c >= '0' && c <= '9' ) return 1; // number |
tomvdb | 0:c52ead8719b3 | 1659 | if( c >= 'A' && c <= 'Z' ) return 1; // LETTER |
tomvdb | 0:c52ead8719b3 | 1660 | if( c >= 'a' && c <= 'z' ) return 1; // letter (for completeness) |
tomvdb | 0:c52ead8719b3 | 1661 | if( c == '_' ) return 1; |
tomvdb | 0:c52ead8719b3 | 1662 | if( c == '+' ) return 1; |
tomvdb | 0:c52ead8719b3 | 1663 | if( c == '.' ) return 1; |
tomvdb | 0:c52ead8719b3 | 1664 | if( c == '~' ) return 1; // Window~1.txt |
tomvdb | 0:c52ead8719b3 | 1665 | |
tomvdb | 0:c52ead8719b3 | 1666 | return 0; |
tomvdb | 0:c52ead8719b3 | 1667 | } |
tomvdb | 0:c52ead8719b3 | 1668 | |
tomvdb | 0:c52ead8719b3 | 1669 | unsigned char * filenameWord(void) |
tomvdb | 0:c52ead8719b3 | 1670 | { |
tomvdb | 0:c52ead8719b3 | 1671 | // SDL - I wasn't sure if this functionality existed above, so I figured i'd put it here |
tomvdb | 0:c52ead8719b3 | 1672 | unsigned char * ret = txtpos; |
tomvdb | 0:c52ead8719b3 | 1673 | expression_error = 0; |
tomvdb | 0:c52ead8719b3 | 1674 | |
tomvdb | 0:c52ead8719b3 | 1675 | // make sure there are no quotes or spaces, search for valid characters |
tomvdb | 0:c52ead8719b3 | 1676 | //while(*txtpos == SPACE || *txtpos == TAB || *txtpos == SQUOTE || *txtpos == DQUOTE ) txtpos++; |
tomvdb | 0:c52ead8719b3 | 1677 | while( !isValidFnChar( *txtpos )) txtpos++; |
tomvdb | 0:c52ead8719b3 | 1678 | ret = txtpos; |
tomvdb | 0:c52ead8719b3 | 1679 | |
tomvdb | 0:c52ead8719b3 | 1680 | if( *ret == '\0' ) { |
tomvdb | 0:c52ead8719b3 | 1681 | expression_error = 1; |
tomvdb | 0:c52ead8719b3 | 1682 | return ret; |
tomvdb | 0:c52ead8719b3 | 1683 | } |
tomvdb | 0:c52ead8719b3 | 1684 | |
tomvdb | 0:c52ead8719b3 | 1685 | // now, find the next nonfnchar |
tomvdb | 0:c52ead8719b3 | 1686 | txtpos++; |
tomvdb | 0:c52ead8719b3 | 1687 | while( isValidFnChar( *txtpos )) txtpos++; |
tomvdb | 0:c52ead8719b3 | 1688 | if( txtpos != ret ) *txtpos = '\0'; |
tomvdb | 0:c52ead8719b3 | 1689 | |
tomvdb | 0:c52ead8719b3 | 1690 | // set the error code if we've got no string |
tomvdb | 0:c52ead8719b3 | 1691 | if( *ret == '\0' ) { |
tomvdb | 0:c52ead8719b3 | 1692 | expression_error = 1; |
tomvdb | 0:c52ead8719b3 | 1693 | } |
tomvdb | 0:c52ead8719b3 | 1694 | |
tomvdb | 0:c52ead8719b3 | 1695 | return ret; |
tomvdb | 0:c52ead8719b3 | 1696 | } |
tomvdb | 0:c52ead8719b3 | 1697 | |
tomvdb | 0:c52ead8719b3 | 1698 | /***************************************************************************/ |
tomvdb | 0:c52ead8719b3 | 1699 | static void line_terminator(void) |
tomvdb | 0:c52ead8719b3 | 1700 | { |
tomvdb | 0:c52ead8719b3 | 1701 | outchar(NL); |
tomvdb | 0:c52ead8719b3 | 1702 | outchar(CR); |
tomvdb | 0:c52ead8719b3 | 1703 | } |
tomvdb | 0:c52ead8719b3 | 1704 | /***********************************************************/ |
tomvdb | 0:c52ead8719b3 | 1705 | static unsigned char breakcheck(void) |
tomvdb | 0:c52ead8719b3 | 1706 | { |
tomvdb | 0:c52ead8719b3 | 1707 | if(pc.readable()) |
tomvdb | 0:c52ead8719b3 | 1708 | return pc.getc() == CTRLC; |
tomvdb | 0:c52ead8719b3 | 1709 | return 0; |
tomvdb | 0:c52ead8719b3 | 1710 | } |
tomvdb | 0:c52ead8719b3 | 1711 | /***********************************************************/ |
tomvdb | 0:c52ead8719b3 | 1712 | static int inchar() |
tomvdb | 0:c52ead8719b3 | 1713 | { |
tomvdb | 0:c52ead8719b3 | 1714 | int v; |
tomvdb | 0:c52ead8719b3 | 1715 | |
tomvdb | 0:c52ead8719b3 | 1716 | switch( inStream ) { |
tomvdb | 0:c52ead8719b3 | 1717 | case( kStreamFile ): |
tomvdb | 0:c52ead8719b3 | 1718 | #ifdef ENABLE_FILEIO |
tomvdb | 0:c52ead8719b3 | 1719 | v = fp.read(); |
tomvdb | 0:c52ead8719b3 | 1720 | if( v == NL ) v=CR; // file translate |
tomvdb | 0:c52ead8719b3 | 1721 | if( !fp.available() ) { |
tomvdb | 0:c52ead8719b3 | 1722 | fp.close(); |
tomvdb | 0:c52ead8719b3 | 1723 | goto inchar_loadfinish; |
tomvdb | 0:c52ead8719b3 | 1724 | } |
tomvdb | 0:c52ead8719b3 | 1725 | return v; |
tomvdb | 0:c52ead8719b3 | 1726 | #else |
tomvdb | 0:c52ead8719b3 | 1727 | #endif |
tomvdb | 0:c52ead8719b3 | 1728 | break; |
tomvdb | 0:c52ead8719b3 | 1729 | case( kStreamEEProm ): |
tomvdb | 0:c52ead8719b3 | 1730 | #ifdef ENABLE_EEPROM |
tomvdb | 0:c52ead8719b3 | 1731 | v = EEPROM.read( eepos++ ); |
tomvdb | 0:c52ead8719b3 | 1732 | if( v == '\0' ) { |
tomvdb | 0:c52ead8719b3 | 1733 | goto inchar_loadfinish; |
tomvdb | 0:c52ead8719b3 | 1734 | } |
tomvdb | 0:c52ead8719b3 | 1735 | return v; |
tomvdb | 0:c52ead8719b3 | 1736 | #endif |
tomvdb | 0:c52ead8719b3 | 1737 | break; |
tomvdb | 0:c52ead8719b3 | 1738 | case( kStreamSerial ): |
tomvdb | 0:c52ead8719b3 | 1739 | default: |
tomvdb | 0:c52ead8719b3 | 1740 | while(1) |
tomvdb | 0:c52ead8719b3 | 1741 | { |
tomvdb | 0:c52ead8719b3 | 1742 | if(pc.readable()) |
tomvdb | 0:c52ead8719b3 | 1743 | return pc.getc(); |
tomvdb | 0:c52ead8719b3 | 1744 | } |
tomvdb | 0:c52ead8719b3 | 1745 | } |
tomvdb | 0:c52ead8719b3 | 1746 | |
tomvdb | 0:c52ead8719b3 | 1747 | inchar_loadfinish: |
tomvdb | 0:c52ead8719b3 | 1748 | inStream = kStreamSerial; |
tomvdb | 0:c52ead8719b3 | 1749 | inhibitOutput = false; |
tomvdb | 0:c52ead8719b3 | 1750 | |
tomvdb | 0:c52ead8719b3 | 1751 | if( runAfterLoad ) { |
tomvdb | 0:c52ead8719b3 | 1752 | runAfterLoad = false; |
tomvdb | 0:c52ead8719b3 | 1753 | triggerRun = true; |
tomvdb | 0:c52ead8719b3 | 1754 | } |
tomvdb | 0:c52ead8719b3 | 1755 | return NL; // trigger a prompt. |
tomvdb | 0:c52ead8719b3 | 1756 | |
tomvdb | 0:c52ead8719b3 | 1757 | } |
tomvdb | 0:c52ead8719b3 | 1758 | /***********************************************************/ |
tomvdb | 0:c52ead8719b3 | 1759 | static void outchar(unsigned char c) |
tomvdb | 0:c52ead8719b3 | 1760 | { |
tomvdb | 0:c52ead8719b3 | 1761 | if( inhibitOutput ) return; |
tomvdb | 0:c52ead8719b3 | 1762 | |
tomvdb | 0:c52ead8719b3 | 1763 | pc.putc(c); |
tomvdb | 0:c52ead8719b3 | 1764 | } |
tomvdb | 0:c52ead8719b3 | 1765 | /***********************************************************/ |
tomvdb | 0:c52ead8719b3 | 1766 | int main() |
tomvdb | 0:c52ead8719b3 | 1767 | { |
tomvdb | 0:c52ead8719b3 | 1768 | while (1) |
tomvdb | 0:c52ead8719b3 | 1769 | { |
tomvdb | 0:c52ead8719b3 | 1770 | loop(); |
tomvdb | 0:c52ead8719b3 | 1771 | } |
tomvdb | 0:c52ead8719b3 | 1772 | } |
tomvdb | 0:c52ead8719b3 | 1773 |