A port of TinyBasic Plus (https://github.com/BleuLlama/TinyBasicPlus) to mbed (focus on Nucleo)

Dependencies:   mbed

Committer:
tomvdb
Date:
Wed Jan 21 15:32:36 2015 +0000
Revision:
0:c52ead8719b3
initial commit

Who changed what in which revision?

UserRevisionLine numberNew 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