Advertisement
Astranome

ESP32BasicFabgl

Jul 28th, 2020
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 55.29 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////////
  2. //             TinyBasic Plus + FabGL VGA library + PS2 keyboard        //
  3. //               for VGA monitor output - May 2019                      //
  4. //                                                                      //
  5. //          Author: Rob Cai <rocaj74@gmail.com>                         //
  6. //                                                                      //
  7. //      Connections:                                                    //
  8. //      Keyboard Data to ESP32 pin 32;                                  //
  9. //      Keyboard IRQ (clock) to ESP32 pin 33;                           //
  10. //      VGA RGB to ESP32 pin 2, 15 and 21 respectively                  //
  11. //      VGA Hsybc and Vsync to ESP32 pins 17 and 4                      //
  12. //                                                                      //
  13. //////////////////////////////////////////////////////////////////////////
  14. //
  15. // NB per usare la scheda SD sembra vadano usati i pin: 5, 18, 19, 23 (SC, clock, MISO, MOSO)
  16. //
  17. // Authors: Mike Field <hamster@snap.net.nz>
  18. //      Scott Lawrence <yorgle@gmail.com>
  19. //          Brian O'Dell <megamemnon@megamemnon.com>
  20. //
  21.  
  22. #define kVersion "v0.14"
  23.  
  24. // v0.14: 2013-11-07
  25. //      Input command always set the variable to 99
  26. //      Modified Input command to accept an expression using getn()
  27. //      Syntax is "input x" where x is any variable
  28. //
  29. // v0.13: 2013-03-04
  30. //      Support for Arduino 1.5 (SPI.h included, additional changes for DUE support)
  31. //
  32. // v0.12: 2013-03-01
  33. //      EEPROM load and save routines added: EFORMAT, ELIST, ELOAD, ESAVE, ECHAIN
  34. //      added EAUTORUN option (chains to EEProm saved program on startup)
  35. //      Bugfixes to build properly on non-arduino systems (PROGMEM #define workaround)
  36. //      cleaned up a bit of the #define options wrt TONE
  37. //
  38. // v0.11: 2013-02-20
  39. //      all display strings and tables moved to PROGMEM to save space
  40. //      removed second serial
  41. //      removed pinMode completely, autoconf is explicit
  42. //      beginnings of EEPROM related functionality (new,load,save,list)
  43. //
  44. // v0.10: 2012-10-15
  45. //      added kAutoConf, which eliminates the "PINMODE" statement.
  46. //      now, DWRITE,DREAD,AWRITE,AREAD automatically set the PINMODE appropriately themselves.
  47. //      should save a few bytes in your programs.
  48. //
  49. // v0.09: 2012-10-12
  50. //      Fixed directory listings.  FILES now always works. (bug in the SD library)
  51. //      ref: http://arduino.cc/forum/index.php/topic,124739.0.html
  52. //      fixed filesize printouts (added printUnum for unsigned numbers)
  53. //      #defineable baud rate for slow connection throttling
  54. //e
  55. // v0.08: 2012-10-02
  56. //      Tone generation through piezo added (TONE, TONEW, NOTONE)
  57. //
  58. // v0.07: 2012-09-30
  59. //      Autorun buildtime configuration feature
  60. //
  61. // v0.06: 2012-09-27
  62. //      Added optional second serial input, used for an external keyboard
  63. //
  64. // v0.05: 2012-09-21
  65. //      CHAIN to load and run a second file
  66. //      RND,RSEED for random stuff
  67. //      Added "!=" for "<>" synonym
  68. //      Added "END" for "STOP" synonym (proper name for the functionality anyway)
  69. //
  70. // v0.04: 2012-09-20
  71. //      DELAY ms   - for delaying
  72. //      PINMODE <pin>, INPUT|IN|I|OUTPUT|OUT|O
  73. //      DWRITE <pin>, HIGH|HI|1|LOW|LO|0
  74. //      AWRITE <pin>, [0..255]
  75. //      fixed "save" appending to existing files instead of overwriting
  76. //  Updated for building desktop command line app (incomplete)
  77. //
  78. // v0.03: 2012-09-19
  79. //  Integrated Jurg Wullschleger whitespace,unary fix
  80. //  Now available through github
  81. //  Project renamed from "Tiny Basic in C" to "TinyBasic Plus"
  82. //     
  83. // v0.02b: 2012-09-17  Scott Lawrence <yorgle@gmail.com>
  84. //  Better FILES listings
  85. //
  86. // v0.02a: 2012-09-17  Scott Lawrence <yorgle@gmail.com>
  87. //  Support for SD Library
  88. //  Added: SAVE, FILES (mostly works), LOAD (mostly works) (redirects IO)
  89. //  Added: MEM, ? (PRINT)
  90. //  Quirk:  "10 LET A=B+C" is ok "10 LET A = B + C" is not.
  91. //  Quirk:  INPUT seems broken?
  92.  
  93. // IF testing with Visual C, this needs to be the first thing in the file.
  94. //#include "stdafx.h"
  95.  
  96. char eliminateCompileErrors = 1;  // fix to suppress arduino build errors
  97. int myScreen;
  98.  
  99. // hack to let makefiles work with this file unchanged
  100. #ifdef FORCE_DESKTOP
  101. #undef ARDUINO
  102. #include "desktop.h"
  103. #else
  104. #define ARDUINO 1
  105. #endif
  106.  
  107.  
  108. ////////////////////////////////////////////////////////////////////////////////
  109. // Feature option configuration...
  110.  
  111. //---------------------------------------------------------------- qui per attivare la scheda SD ---------------------------------------------------------
  112. // This enables LOAD, SAVE, FILES commands through the Arduino SD Library
  113. // it adds 9k of usage as well.
  114. #define ENABLE_FILEIO 1
  115. //#undef ENABLE_FILEIO //-------------------------- commentando questo la memoria passa da 2810 bytes a 1771 bytes ---------------------------------------
  116.  
  117. // this turns on "autorun".  if there's FileIO, and a file "autorun.bas",
  118. // then it will load it and run it when starting up
  119. //#define ENABLE_AUTORUN 1
  120. #undef ENABLE_AUTORUN
  121. // and this is the file that gets run
  122. #define kAutorunFilename  "autorun.bas"
  123.  
  124. // this is the alternate autorun.  Autorun the program in the eeprom.
  125. // it will load whatever is in the EEProm and run it
  126. #define ENABLE_EAUTORUN 1
  127. //#undef ENABLE_EAUTORUN
  128.  
  129. // this will enable the "TONE", "NOTONE" command using a piezo
  130. // element on the specified pin.  Wire the red/positive/piezo to the kPiezoPin,
  131. // and the black/negative/metal disc to ground.
  132. // it adds 1.5k of usage as well.
  133. #define ENABLE_TONES 1
  134. //#undef ENABLE_TONES
  135. #define kPiezoPin 6 //------------------------------------------ default era 5 -----------------------------------
  136.  
  137. // we can use the EEProm to store a program during powerdown.  This is
  138. // 1kbyte on the '328, and 512 bytes on the '168.  Enabling this here will
  139. // allow for this funcitonality to work.  Note that this only works on AVR
  140. // arduino.  Disable it for DUE/other devices.
  141. #define ENABLE_EEPROM 1
  142. //#undef ENABLE_EEPROM
  143.  
  144. #include "fabgl.h" //******************************************************** qui include la libreria per l'uso di VGA *********************************************
  145.  
  146. void print_info()
  147. {
  148.   Terminal.write("\e[33m    ESP32 TinyBasic PC with VGA monitor and PS2keyboard\r\n");
  149.   Terminal.write("\e[32m    by Roberto Melzi\e[32m\r\n\n");
  150.   Terminal.write("\e[37m    FabGL - Loopback VT/ANSI Terminal\r\n");
  151.   Terminal.write("\e[37m    2019 by Fabrizio Di Vittorio - www.fabgl.com\e[32m\r\n\n");
  152.   Terminal.printf("\e[31mScreen Size        :\e[33m %d x %d\r\n", VGAController.getScreenWidth(), VGAController.getScreenHeight());
  153.   Terminal.printf("\e[32mTerminal Size      :\e[33m %d x %d\r\n", Terminal.getColumns(), Terminal.getRows());
  154.   Terminal.printf("\e[37mKeyboard           :\e[33m %s\r\n", Keyboard.isKeyboardAvailable() ? "OK" : "Error");
  155.   Terminal.printf("\e[35mFree DMA Memory    :\e[33m %d\r\n", heap_caps_get_free_size(MALLOC_CAP_DMA));
  156.   Terminal.printf("\e[36mFree 32 bit Memory :\e[33m %d\r\n\n", heap_caps_get_free_size(MALLOC_CAP_32BIT));
  157.   Terminal.write("\e[32mFree typing test - press ESC to introduce escape VT/ANSI codes\r\n\n");
  158. }
  159.  
  160.  
  161. // Sometimes, we connect with a slower device as the console.
  162. // Set your console D0/D1 baud rate here (9600 baud default)
  163. //#define kConsoleBaud 9600
  164. #define kConsoleBaud 115200 //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
  165.  
  166. ////////////////////////////////////////////////////////////////////////////////
  167. #ifdef ARDUINO
  168. #ifndef RAMEND
  169. // okay, this is a hack for now
  170. // if we're in here, we're a DUE probably (ARM instead of AVR)
  171.  
  172. //#define RAMEND 4096-1
  173. #define RAMEND 16384-1  //-------------------------- RAM increment for ESP32 ---------------------------------------------------
  174.  
  175. // turn off EEProm
  176. #undef ENABLE_EEPROM //----------------------------- provo a commentare questo ma non va ---------------------------------------
  177. #undef ENABLE_TONES  //----------------------------- provo a commentare questo ma non va ---------------------------------------
  178.  
  179. #else
  180. // we're an AVR!
  181.  
  182. // we're moving our data strings into progmem
  183. #include <avr/pgmspace.h>
  184. #endif
  185.  
  186. // includes, and settings for Arduino-specific functionality
  187. #ifdef ENABLE_EEPROM
  188. #include <EEPROM.h>  /* NOTE: case sensitive */
  189. int eepos = 0;
  190. #endif
  191.  
  192. #ifdef ENABLE_FILEIO
  193. #include <FS.h>
  194. #include <SD.h>
  195. #include <SPI.h> /* needed as of 1.5 beta */
  196.  
  197. // Arduino-specific configuration
  198. // set this to the card select for your SD shield
  199. #define kSD_CS 5  // ------------------------ old era 10 -------------------------------------------------------------
  200.  
  201. #define kSD_Fail  0
  202. #define kSD_OK    1
  203.  
  204. File fp;
  205. #endif
  206.  
  207. // set up our RAM buffer size for program and user input
  208. // NOTE: This number will have to change if you include other libraries.
  209. #ifdef ARDUINO
  210. #ifdef ENABLE_FILEIO
  211. #define kRamFileIO (1030) /* approximate */
  212. #else
  213. #define kRamFileIO (0)
  214. #endif
  215. #ifdef ENABLE_TONES
  216. #define kRamTones (40)
  217. #else
  218. #define kRamTones (0)
  219. #endif
  220. #endif /* ARDUINO */
  221. #define kRamSize  (RAMEND - 1160 - kRamFileIO - kRamTones)
  222.  
  223. #ifndef ARDUINO
  224. // Not arduino setup
  225. #include <stdio.h>
  226. #include <stdlib.h>
  227. #undef ENABLE_TONES
  228.  
  229. // size of our program ram
  230. #define kRamSize   4096 /* arbitrary */
  231. //#define kRamSize   16384 /* arbitrary */ //-------------------------------------------------------------- kRamSize -------------------------------------------------------------------------
  232.  
  233. #ifdef ENABLE_FILEIO
  234. FILE * fp;
  235. #endif
  236. #endif
  237.  
  238. #ifdef ENABLE_FILEIO
  239. // functions defined elsehwere
  240. void cmd_Files( void );
  241. #endif
  242.  
  243. ////////////////////
  244.  
  245. #ifndef boolean
  246. #define boolean int
  247. #define true 1
  248. #define false 0
  249. #endif
  250. #endif
  251.  
  252. #ifndef byte
  253. typedef unsigned char byte;
  254. #endif
  255.  
  256. // some catches for AVR based text string stuff...
  257. #ifndef PROGMEM
  258. #define PROGMEM
  259. #endif
  260. #ifndef pgm_read_byte
  261. #define pgm_read_byte( A ) *(A)
  262. #endif
  263.  
  264. ////////////////////
  265.  
  266. #ifdef ENABLE_FILEIO
  267. unsigned char * filenameWord(void);
  268. static boolean sd_is_initialized = false;
  269. #endif
  270.  
  271. boolean inhibitOutput = false;
  272. static boolean runAfterLoad = false;
  273. static boolean triggerRun = false;
  274.  
  275. // these will select, at runtime, where IO happens through for load/save
  276. enum {
  277.   kStreamSerial = 0,
  278.   kStreamEEProm,
  279.   kStreamFile
  280. };
  281. static unsigned char inStream = kStreamSerial;
  282. static unsigned char outStream = kStreamSerial;
  283.  
  284.  
  285. ////////////////////////////////////////////////////////////////////////////////
  286. // ASCII Characters
  287. #define CR  '\r'
  288. #define NL  '\n'
  289. #define LF      0x0a
  290. #define TAB '\t'
  291. #define BELL    '\b'
  292. #define SPACE   ' '
  293. #define SQUOTE  '\''
  294. #define DQUOTE  '\"'
  295. #define CTRLC   0x03
  296. #define CTRLH   0x08
  297. #define CTRLS   0x13
  298. #define CTRLX   0x18
  299.  
  300. typedef short unsigned LINENUM;
  301. #ifdef ARDUINO
  302. #define ECHO_CHARS 1
  303. #else
  304. #define ECHO_CHARS 0
  305. #endif
  306.  
  307.  
  308. static unsigned char program[kRamSize];
  309. static const char *  sentinel = "HELLO";
  310. static unsigned char *txtpos,*list_line, *tmptxtpos;
  311. static unsigned char expression_error;
  312. static unsigned char *tempsp;
  313.  
  314. /***********************************************************/
  315. // Keyword table and constants - the last character has 0x80 added to it
  316. const static unsigned char keywords[] PROGMEM = {
  317.   'L','I','S','T'+0x80,
  318.   'L','O','A','D'+0x80,
  319.   'N','E','W'+0x80,
  320.   'R','U','N'+0x80,
  321.   'S','A','V','E'+0x80,
  322.   'N','E','X','T'+0x80,
  323.   'L','E','T'+0x80,
  324.   'I','F'+0x80,
  325.   'G','O','T','O'+0x80,
  326.   'G','O','S','U','B'+0x80,
  327.   'R','E','T','U','R','N'+0x80,
  328.   'R','E','M'+0x80,
  329.   'F','O','R'+0x80,
  330.   'I','N','P','U','T'+0x80,
  331.   'P','R','I','N','T'+0x80,
  332.   'P','O','K','E'+0x80,
  333.   'S','T','O','P'+0x80,
  334.   'B','Y','E'+0x80,
  335.   'F','I','L','E','S'+0x80,
  336.   'M','E','M'+0x80,
  337.   '?'+ 0x80,
  338.   '\''+ 0x80,
  339.   'A','W','R','I','T','E'+0x80,
  340.   'D','W','R','I','T','E'+0x80,
  341.   'D','E','L','A','Y'+0x80,
  342.   'E','N','D'+0x80,
  343.   'R','S','E','E','D'+0x80,
  344.   'C','H','A','I','N'+0x80,
  345. #ifdef ENABLE_TONES
  346.   'T','O','N','E','W'+0x80,
  347.   'T','O','N','E'+0x80,
  348.   'N','O','T','O','N','E'+0x80,
  349. #endif
  350. #ifdef ARDUINO
  351. #ifdef ENABLE_EEPROM
  352.   'E','C','H','A','I','N'+0x80,
  353.   'E','L','I','S','T'+0x80,
  354.   'E','L','O','A','D'+0x80,
  355.   'E','F','O','R','M','A','T'+0x80,
  356.   'E','S','A','V','E'+0x80,
  357. #endif
  358. #endif
  359.   0
  360. };
  361.  
  362. // by moving the command list to an enum, we can easily remove sections
  363. // above and below simultaneously to selectively obliterate functionality.
  364. enum {
  365.   KW_LIST = 0,
  366.   KW_LOAD, KW_NEW, KW_RUN, KW_SAVE,
  367.   KW_NEXT, KW_LET, KW_IF,
  368.   KW_GOTO, KW_GOSUB, KW_RETURN,
  369.   KW_REM,
  370.   KW_FOR,
  371.   KW_INPUT, KW_PRINT,
  372.   KW_POKE,
  373.   KW_STOP, KW_BYE,
  374.   KW_FILES,
  375.   KW_MEM,
  376.   KW_QMARK, KW_QUOTE,
  377.   KW_AWRITE, KW_DWRITE,
  378.   KW_DELAY,
  379.   KW_END,
  380.   KW_RSEED,
  381.   KW_CHAIN,
  382. #ifdef ENABLE_TONES
  383.   KW_TONEW, KW_TONE, KW_NOTONE,
  384. #endif
  385. #ifdef ARDUINO
  386. #ifdef ENABLE_EEPROM
  387.   KW_ECHAIN, KW_ELIST, KW_ELOAD, KW_EFORMAT, KW_ESAVE,
  388. #endif
  389. #endif
  390.   KW_DEFAULT /* always the final one*/
  391. };
  392.  
  393. struct stack_for_frame {
  394.   char frame_type;
  395.   char for_var;
  396.   short int terminal;
  397.   short int step;
  398.   unsigned char *current_line;
  399.   unsigned char *txtpos;
  400. };
  401.  
  402. struct stack_gosub_frame {
  403.   char frame_type;
  404.   unsigned char *current_line;
  405.   unsigned char *txtpos;
  406. };
  407.  
  408. const static unsigned char func_tab[] PROGMEM = {
  409.   'P','E','E','K'+0x80,
  410.   'A','B','S'+0x80,
  411.   'A','R','E','A','D'+0x80,
  412.   'D','R','E','A','D'+0x80,
  413.   'R','N','D'+0x80,
  414.   0
  415. };
  416. #define FUNC_PEEK    0
  417. #define FUNC_ABS     1
  418. #define FUNC_AREAD   2
  419. #define FUNC_DREAD   3
  420. #define FUNC_RND     4
  421. #define FUNC_UNKNOWN 5
  422.  
  423. const static unsigned char to_tab[] PROGMEM = {
  424.   'T','O'+0x80,
  425.   0
  426. };
  427.  
  428. const static unsigned char step_tab[] PROGMEM = {
  429.   'S','T','E','P'+0x80,
  430.   0
  431. };
  432.  
  433. const static unsigned char relop_tab[] PROGMEM = {
  434.   '>','='+0x80,
  435.   '<','>'+0x80,
  436.   '>'+0x80,
  437.   '='+0x80,
  438.   '<','='+0x80,
  439.   '<'+0x80,
  440.   '!','='+0x80,
  441.   0
  442. };
  443.  
  444. #define RELOP_GE        0
  445. #define RELOP_NE        1
  446. #define RELOP_GT        2
  447. #define RELOP_EQ        3
  448. #define RELOP_LE        4
  449. #define RELOP_LT        5
  450. #define RELOP_NE_BANG       6
  451. #define RELOP_UNKNOWN   7
  452.  
  453. const static unsigned char highlow_tab[] PROGMEM = {
  454.   'H','I','G','H'+0x80,
  455.   'H','I'+0x80,
  456.   'L','O','W'+0x80,
  457.   'L','O'+0x80,
  458.   0
  459. };
  460. #define HIGHLOW_HIGH    1
  461. #define HIGHLOW_UNKNOWN 4
  462.  
  463. #define STACK_SIZE (sizeof(struct stack_for_frame)*5)
  464. #define VAR_SIZE sizeof(short int) // Size of variables in bytes
  465.  
  466. static unsigned char *stack_limit;
  467. static unsigned char *program_start;
  468. static unsigned char *program_end;
  469. static unsigned char *stack; // Software stack for things that should go on the CPU stack
  470. static unsigned char *variables_begin;
  471. static unsigned char *current_line;
  472. static unsigned char *sp;
  473. #define STACK_GOSUB_FLAG 'G'
  474. #define STACK_FOR_FLAG 'F'
  475. static unsigned char table_index;
  476. static LINENUM linenum;
  477.  
  478. static const unsigned char okmsg[]            PROGMEM = "OK";
  479. static const unsigned char whatmsg[]          PROGMEM = "What? ";
  480. static const unsigned char howmsg[]           PROGMEM = "How?";
  481. static const unsigned char sorrymsg[]         PROGMEM = "Sorry!";
  482. static const unsigned char initmsg[]          PROGMEM = "TinyBasic Plus " kVersion;
  483. static const unsigned char memorymsg[]        PROGMEM = " bytes free.";
  484. #ifdef ARDUINO
  485. #ifdef ENABLE_EEPROM
  486. static const unsigned char eeprommsg[]        PROGMEM = " EEProm bytes total.";
  487. static const unsigned char eepromamsg[]       PROGMEM = " EEProm bytes available.";
  488. #endif
  489. #endif
  490. static const unsigned char breakmsg[]         PROGMEM = "break!";
  491. static const unsigned char unimplimentedmsg[] PROGMEM = "Unimplemented";
  492. static const unsigned char backspacemsg[]     PROGMEM = "\b \b";
  493. static const unsigned char indentmsg[]        PROGMEM = "    ";
  494. static const unsigned char sderrormsg[]       PROGMEM = "SD card error.";
  495. static const unsigned char sdfilemsg[]        PROGMEM = "SD file error.";
  496. static const unsigned char dirextmsg[]        PROGMEM = "(dir)";
  497. static const unsigned char slashmsg[]         PROGMEM = "/";
  498. static const unsigned char spacemsg[]         PROGMEM = " ";
  499.  
  500. static int inchar(void);
  501. static void outchar(unsigned char c);
  502. static void line_terminator(void);
  503. static short int expression(void);
  504. static unsigned char breakcheck(void);
  505. /***************************************************************************/
  506. static void ignore_blanks(void)
  507. {
  508.   while(*txtpos == SPACE || *txtpos == TAB)
  509.     txtpos++;
  510. }
  511.  
  512.  
  513. /***************************************************************************/
  514. static void scantable(const unsigned char *table)
  515. {
  516.   int i = 0;
  517.   table_index = 0;
  518.   while(1)
  519.   {
  520.     // Run out of table entries?
  521.     if(pgm_read_byte( table ) == 0)
  522.       return;
  523.  
  524.     // Do we match this character?
  525.     if(txtpos[i] == pgm_read_byte( table ))
  526.     {
  527.       i++;
  528.       table++;
  529.     }
  530.     else
  531.     {
  532.       // do we match the last character of keywork (with 0x80 added)? If so, return
  533.       if(txtpos[i]+0x80 == pgm_read_byte( table ))
  534.       {
  535.         txtpos += i+1;  // Advance the pointer to following the keyword
  536.         ignore_blanks();
  537.         return;
  538.       }
  539.  
  540.       // Forward to the end of this keyword
  541.       while((pgm_read_byte( table ) & 0x80) == 0)
  542.         table++;
  543.  
  544.       // Now move on to the first character of the next word, and reset the position index
  545.       table++;
  546.       table_index++;
  547.       ignore_blanks();
  548.       i = 0;
  549.     }
  550.   }
  551. }
  552.  
  553. /***************************************************************************/
  554. static void pushb(unsigned char b)
  555. {
  556.   sp--;
  557.   *sp = b;
  558. }
  559.  
  560. /***************************************************************************/
  561. static unsigned char popb()
  562. {
  563.   unsigned char b;
  564.   b = *sp;
  565.   sp++;
  566.   return b;
  567. }
  568.  
  569. /***************************************************************************/
  570. void printnum(int num)
  571. {
  572.   int digits = 0;
  573.  
  574.   if(num < 0)
  575.   {
  576.     num = -num;
  577.     outchar('-');
  578.   }
  579.   do {
  580.     pushb(num%10+'0');
  581.     num = num/10;
  582.     digits++;
  583.   }
  584.   while (num > 0);
  585.  
  586.   while(digits > 0)
  587.   {
  588.     outchar(popb());
  589.     digits--;
  590.   }
  591. }
  592.  
  593. void printUnum(unsigned int num)
  594. {
  595.   int digits = 0;
  596.  
  597.   do {
  598.     pushb(num%10+'0');
  599.     num = num/10;
  600.     digits++;
  601.   }
  602.   while (num > 0);
  603.  
  604.   while(digits > 0)
  605.   {
  606.     outchar(popb());
  607.     digits--;
  608.   }
  609. }
  610.  
  611. /***************************************************************************/
  612. static unsigned short testnum(void)
  613. {
  614.   unsigned short num = 0;
  615.   ignore_blanks();
  616.  
  617.   while(*txtpos>= '0' && *txtpos <= '9' )
  618.   {
  619.     // Trap overflows
  620.     if(num >= 0xFFFF/10)
  621.     {
  622.       num = 0xFFFF;
  623.       break;
  624.     }
  625.  
  626.     num = num *10 + *txtpos - '0';
  627.     txtpos++;
  628.   }
  629.   return    num;
  630. }
  631.  
  632. /***************************************************************************/
  633. static unsigned char print_quoted_string(void)
  634. {
  635.   int i=0;
  636.   unsigned char delim = *txtpos;
  637.   if(delim != '"' && delim != '\'')
  638.     return 0;
  639.   txtpos++;
  640.  
  641.   // Check we have a closing delimiter
  642.   while(txtpos[i] != delim)
  643.   {
  644.     if(txtpos[i] == NL)
  645.       return 0;
  646.     i++;
  647.   }
  648.  
  649.   // Print the characters
  650.   while(*txtpos != delim)
  651.   {
  652.     outchar(*txtpos);
  653.     txtpos++;
  654.   }
  655.   txtpos++; // Skip over the last delimiter
  656.  
  657.   return 1;
  658. }
  659.  
  660.  
  661. /***************************************************************************/
  662. void printmsgNoNL(const unsigned char *msg)
  663. {
  664.   while( pgm_read_byte( msg ) != 0 ) {
  665.     outchar( pgm_read_byte( msg++ ) );
  666.   };
  667. }
  668.  
  669. /***************************************************************************/
  670. void printmsg(const unsigned char *msg)
  671. {
  672.   printmsgNoNL(msg);
  673.   line_terminator();
  674. }
  675.  
  676. /***************************************************************************/
  677. static void getln(char prompt)
  678. {
  679.   outchar(prompt);
  680.   txtpos = program_end+sizeof(LINENUM);
  681.  
  682.   while(1)
  683.   {
  684.     char c = inchar();
  685.     switch(c)
  686.     {
  687.     case NL:
  688.       //break;
  689.     case CR:
  690.       line_terminator();
  691.       // Terminate all strings with a NL
  692.       txtpos[0] = NL;
  693.       return;
  694.     case CTRLH:
  695.       if(txtpos == program_end)
  696.         break;
  697.       txtpos--;
  698.  
  699.       printmsg(backspacemsg);
  700.       break;
  701.     default:
  702.       // We need to leave at least one space to allow us to shuffle the line into order
  703.       if(txtpos == variables_begin-2)
  704.         outchar(BELL);
  705.       else
  706.       {
  707.         txtpos[0] = c;
  708.         txtpos++;
  709.         outchar(c);
  710.       }
  711.     }
  712.   }
  713. }
  714.  
  715. /***************************************************************************/
  716. static unsigned char *findline(void)
  717. {
  718.   unsigned char *line = program_start;
  719.   while(1)
  720.   {
  721.     if(line == program_end)
  722.       return line;
  723.  
  724.     if(((LINENUM *)line)[0] >= linenum)
  725.       return line;
  726.  
  727.     // Add the line length onto the current address, to get to the next line;
  728.     line += line[sizeof(LINENUM)];
  729.   }
  730. }
  731.  
  732. /***************************************************************************/
  733. static void toUppercaseBuffer(void)
  734. {
  735.   unsigned char *c = program_end+sizeof(LINENUM);
  736.   unsigned char quote = 0;
  737.  
  738.   while(*c != NL)
  739.   {
  740.     // Are we in a quoted string?
  741.     if(*c == quote)
  742.       quote = 0;
  743.     else if(*c == '"' || *c == '\'')
  744.       quote = *c;
  745.     else if(quote == 0 && *c >= 'a' && *c <= 'z')
  746.       *c = *c + 'A' - 'a';
  747.     c++;
  748.   }
  749. }
  750.  
  751. /***************************************************************************/
  752. void printline()
  753. {
  754.   LINENUM line_num;
  755.  
  756.   line_num = *((LINENUM *)(list_line));
  757.   list_line += sizeof(LINENUM) + sizeof(char);
  758.  
  759.   // Output the line */
  760.   printnum(line_num);
  761.   outchar(' ');
  762.   while(*list_line != NL)
  763.   {
  764.     outchar(*list_line);
  765.     list_line++;
  766.   }
  767.   list_line++;
  768.   line_terminator();
  769. }
  770.  
  771. /***************************************************************************/
  772. static short int expr4(void)
  773. {
  774.   // fix provided by Jurg Wullschleger wullschleger@gmail.com
  775.   // fixes whitespace and unary operations
  776.   ignore_blanks();
  777.  
  778.   if( *txtpos == '-' ) {
  779.     txtpos++;
  780.     return -expr4();
  781.   }
  782.   // end fix
  783.  
  784.   if(*txtpos == '0')
  785.   {
  786.     txtpos++;
  787.     return 0;
  788.   }
  789.  
  790.   if(*txtpos >= '1' && *txtpos <= '9')
  791.   {
  792.     short int a = 0;
  793.     do  {
  794.       a = a*10 + *txtpos - '0';
  795.       txtpos++;
  796.     }
  797.     while(*txtpos >= '0' && *txtpos <= '9');
  798.     return a;
  799.   }
  800.  
  801.   // Is it a function or variable reference?
  802.   if(txtpos[0] >= 'A' && txtpos[0] <= 'Z')
  803.   {
  804.     short int a;
  805.     // Is it a variable reference (single alpha)
  806.     if(txtpos[1] < 'A' || txtpos[1] > 'Z')
  807.     {
  808.       a = ((short int *)variables_begin)[*txtpos - 'A'];
  809.       txtpos++;
  810.       return a;
  811.     }
  812.  
  813.     // Is it a function with a single parameter
  814.     scantable(func_tab);
  815.     if(table_index == FUNC_UNKNOWN)
  816.       goto expr4_error;
  817.  
  818.     unsigned char f = table_index;
  819.  
  820.     if(*txtpos != '(')
  821.       goto expr4_error;
  822.  
  823.     txtpos++;
  824.     a = expression();
  825.     if(*txtpos != ')')
  826.       goto expr4_error;
  827.     txtpos++;
  828.     switch(f)
  829.     {
  830.     case FUNC_PEEK:
  831.       return program[a];
  832.      
  833.     case FUNC_ABS:
  834.       if(a < 0)
  835.         return -a;
  836.       return a;
  837.  
  838. #ifdef ARDUINO
  839.     case FUNC_AREAD:
  840.       pinMode( a, INPUT );
  841.       return analogRead( a );                        
  842.     case FUNC_DREAD:
  843.       pinMode( a, INPUT );
  844.       return digitalRead( a );
  845. #endif
  846.  
  847.     case FUNC_RND:
  848. #ifdef ARDUINO
  849.       return( random( a ));
  850. #else
  851.       return( rand() % a );
  852. #endif
  853.     }
  854.   }
  855.  
  856.   if(*txtpos == '(')
  857.   {
  858.     short int a;
  859.     txtpos++;
  860.     a = expression();
  861.     if(*txtpos != ')')
  862.       goto expr4_error;
  863.  
  864.     txtpos++;
  865.     return a;
  866.   }
  867.  
  868. expr4_error:
  869.   expression_error = 1;
  870.   return 0;
  871.  
  872. }
  873.  
  874. /***************************************************************************/
  875. static short int expr3(void)
  876. {
  877.   short int a,b;
  878.  
  879.   a = expr4();
  880.  
  881.   ignore_blanks(); // fix for eg:  100 a = a + 1
  882.  
  883.   while(1)
  884.   {
  885.     if(*txtpos == '*')
  886.     {
  887.       txtpos++;
  888.       b = expr4();
  889.       a *= b;
  890.     }
  891.     else if(*txtpos == '/')
  892.     {
  893.       txtpos++;
  894.       b = expr4();
  895.       if(b != 0)
  896.         a /= b;
  897.       else
  898.         expression_error = 1;
  899.     }
  900.     else
  901.       return a;
  902.   }
  903. }
  904.  
  905. /***************************************************************************/
  906. static short int expr2(void)
  907. {
  908.   short int a,b;
  909.  
  910.   if(*txtpos == '-' || *txtpos == '+')
  911.     a = 0;
  912.   else
  913.     a = expr3();
  914.  
  915.   while(1)
  916.   {
  917.     if(*txtpos == '-')
  918.     {
  919.       txtpos++;
  920.       b = expr3();
  921.       a -= b;
  922.     }
  923.     else if(*txtpos == '+')
  924.     {
  925.       txtpos++;
  926.       b = expr3();
  927.       a += b;
  928.     }
  929.     else
  930.       return a;
  931.   }
  932. }
  933. /***************************************************************************/
  934. static short int expression(void)
  935. {
  936.   short int a,b;
  937.  
  938.   a = expr2();
  939.  
  940.   // Check if we have an error
  941.   if(expression_error)  return a;
  942.  
  943.   scantable(relop_tab);
  944.   if(table_index == RELOP_UNKNOWN)
  945.     return a;
  946.  
  947.   switch(table_index)
  948.   {
  949.   case RELOP_GE:
  950.     b = expr2();
  951.     if(a >= b) return 1;
  952.     break;
  953.   case RELOP_NE:
  954.   case RELOP_NE_BANG:
  955.     b = expr2();
  956.     if(a != b) return 1;
  957.     break;
  958.   case RELOP_GT:
  959.     b = expr2();
  960.     if(a > b) return 1;
  961.     break;
  962.   case RELOP_EQ:
  963.     b = expr2();
  964.     if(a == b) return 1;
  965.     break;
  966.   case RELOP_LE:
  967.     b = expr2();
  968.     if(a <= b) return 1;
  969.     break;
  970.   case RELOP_LT:
  971.     b = expr2();
  972.     if(a < b) return 1;
  973.     break;
  974.   }
  975.   return 0;
  976. }
  977.  
  978. /***************************************************************************/
  979. void loop()
  980. {
  981.   Serial.println("&with &V&G&A&x&& video output");
  982.   //Serial.println("Version beta 1.0");
  983.   unsigned char *start;
  984.   unsigned char *newEnd;
  985.   unsigned char linelen;
  986.   boolean isDigital;
  987.   boolean alsoWait = false;
  988.   int val;
  989.  
  990. #ifdef ARDUINO
  991. #ifdef ENABLE_TONES
  992.   noTone( kPiezoPin );
  993. #endif
  994. #endif
  995.  
  996.   program_start = program;
  997.   program_end = program_start;
  998.   sp = program+sizeof(program);  // Needed for printnum
  999.   stack_limit = program+sizeof(program)-STACK_SIZE;
  1000.   variables_begin = stack_limit - 27*VAR_SIZE;
  1001.  
  1002.   // memory free
  1003.   printnum(variables_begin-program_end);
  1004.   printmsg(memorymsg);
  1005. #ifdef ARDUINO
  1006. #ifdef ENABLE_EEPROM
  1007.   // eprom size
  1008.   printnum( E2END+1 );
  1009.   printmsg( eeprommsg );
  1010. #endif /* ENABLE_EEPROM */
  1011. #endif /* ARDUINO */
  1012.  
  1013. warmstart:
  1014.   // this signifies that it is running in 'direct' mode.
  1015.   current_line = 0;
  1016.   sp = program+sizeof(program);
  1017.   printmsg(okmsg);
  1018.  
  1019. prompt:
  1020.   if( triggerRun ){
  1021.     triggerRun = false;
  1022.     current_line = program_start;
  1023.     goto execline;
  1024.   }
  1025.  
  1026.   getln( '>' );
  1027.   toUppercaseBuffer();
  1028.  
  1029.   txtpos = program_end+sizeof(unsigned short);
  1030.  
  1031.   // Find the end of the freshly entered line
  1032.   while(*txtpos != NL)
  1033.     txtpos++;
  1034.  
  1035.   // Move it to the end of program_memory
  1036.   {
  1037.     unsigned char *dest;
  1038.     dest = variables_begin-1;
  1039.     while(1)
  1040.     {
  1041.       *dest = *txtpos;
  1042.       if(txtpos == program_end+sizeof(unsigned short))
  1043.         break;
  1044.       dest--;
  1045.       txtpos--;
  1046.     }
  1047.     txtpos = dest;
  1048.   }
  1049.  
  1050.   // Now see if we have a line number
  1051.   linenum = testnum();
  1052.   ignore_blanks();
  1053.   if(linenum == 0)
  1054.     goto direct;
  1055.  
  1056.   if(linenum == 0xFFFF)
  1057.     goto qhow;
  1058.  
  1059.   // Find the length of what is left, including the (yet-to-be-populated) line header
  1060.   linelen = 0;
  1061.   while(txtpos[linelen] != NL)
  1062.     linelen++;
  1063.   linelen++; // Include the NL in the line length
  1064.   linelen += sizeof(unsigned short)+sizeof(char); // Add space for the line number and line length
  1065.  
  1066.   // Now we have the number, add the line header.
  1067.   txtpos -= 3;
  1068.   *((unsigned short *)txtpos) = linenum;
  1069.   txtpos[sizeof(LINENUM)] = linelen;
  1070.  
  1071.  
  1072.   // Merge it into the rest of the program
  1073.   start = findline();
  1074.  
  1075.   // If a line with that number exists, then remove it
  1076.   if(start != program_end && *((LINENUM *)start) == linenum)
  1077.   {
  1078.     unsigned char *dest, *from;
  1079.     unsigned tomove;
  1080.  
  1081.     from = start + start[sizeof(LINENUM)];
  1082.     dest = start;
  1083.  
  1084.     tomove = program_end - from;
  1085.     while( tomove > 0)
  1086.     {
  1087.       *dest = *from;
  1088.       from++;
  1089.       dest++;
  1090.       tomove--;
  1091.     }  
  1092.     program_end = dest;
  1093.   }
  1094.  
  1095.   if(txtpos[sizeof(LINENUM)+sizeof(char)] == NL) // If the line has no txt, it was just a delete
  1096.     goto prompt;
  1097.  
  1098.  
  1099.  
  1100.   // Make room for the new line, either all in one hit or lots of little shuffles
  1101.   while(linelen > 0)
  1102.   {
  1103.     unsigned int tomove;
  1104.     unsigned char *from,*dest;
  1105.     unsigned int space_to_make;
  1106.  
  1107.     space_to_make = txtpos - program_end;
  1108.  
  1109.     if(space_to_make > linelen)
  1110.       space_to_make = linelen;
  1111.     newEnd = program_end+space_to_make;
  1112.     tomove = program_end - start;
  1113.  
  1114.  
  1115.     // Source and destination - as these areas may overlap we need to move bottom up
  1116.     from = program_end;
  1117.     dest = newEnd;
  1118.     while(tomove > 0)
  1119.     {
  1120.       from--;
  1121.       dest--;
  1122.       *dest = *from;
  1123.       tomove--;
  1124.     }
  1125.  
  1126.     // Copy over the bytes into the new space
  1127.     for(tomove = 0; tomove < space_to_make; tomove++)
  1128.     {
  1129.       *start = *txtpos;
  1130.       txtpos++;
  1131.       start++;
  1132.       linelen--;
  1133.     }
  1134.     program_end = newEnd;
  1135.   }
  1136.   goto prompt;
  1137.  
  1138. unimplemented:
  1139.   printmsg(unimplimentedmsg);
  1140.   goto prompt;
  1141.  
  1142. qhow:  
  1143.   printmsg(howmsg);
  1144.   goto prompt;
  1145.  
  1146. qwhat: 
  1147.   printmsgNoNL(whatmsg);
  1148.   if(current_line != NULL)
  1149.   {
  1150.     unsigned char tmp = *txtpos;
  1151.     if(*txtpos != NL)
  1152.       *txtpos = '^';
  1153.     list_line = current_line;
  1154.     printline();
  1155.     *txtpos = tmp;
  1156.   }
  1157.   line_terminator();
  1158.   goto prompt;
  1159.  
  1160. qsorry:
  1161.   printmsg(sorrymsg);
  1162.   goto warmstart;
  1163.  
  1164. run_next_statement:
  1165.   while(*txtpos == ':')
  1166.     txtpos++;
  1167.   ignore_blanks();
  1168.   if(*txtpos == NL)
  1169.     goto execnextline;
  1170.   goto interperateAtTxtpos;
  1171.  
  1172. direct:
  1173.   txtpos = program_end+sizeof(LINENUM);
  1174.   if(*txtpos == NL)
  1175.     goto prompt;
  1176.  
  1177. interperateAtTxtpos:
  1178.   if(breakcheck())
  1179.   {
  1180.     printmsg(breakmsg);
  1181.     goto warmstart;
  1182.   }
  1183.  
  1184.   scantable(keywords);
  1185.  
  1186.   switch(table_index)
  1187.   {
  1188.   case KW_DELAY:
  1189.     {
  1190. #ifdef ARDUINO
  1191.       expression_error = 0;
  1192.       val = expression();
  1193.       delay( val );
  1194.       goto execnextline;
  1195. #else
  1196.       goto unimplemented;
  1197. #endif
  1198.     }
  1199.  
  1200.   case KW_FILES:
  1201.     goto files;
  1202.   case KW_LIST:
  1203.     goto list;
  1204.   case KW_CHAIN:
  1205.     goto chain;
  1206.   case KW_LOAD:
  1207.     goto load;
  1208.   case KW_MEM:
  1209.     goto mem;
  1210.   case KW_NEW:
  1211.     if(txtpos[0] != NL)
  1212.       goto qwhat;
  1213.     program_end = program_start;
  1214.     goto prompt;
  1215.   case KW_RUN:
  1216.     current_line = program_start;
  1217.     goto execline;
  1218.   case KW_SAVE:
  1219.     goto save;
  1220.   case KW_NEXT:
  1221.     goto next;
  1222.   case KW_LET:
  1223.     goto assignment;
  1224.   case KW_IF:
  1225.     short int val;
  1226.     expression_error = 0;
  1227.     val = expression();
  1228.     if(expression_error || *txtpos == NL)
  1229.       goto qhow;
  1230.     if(val != 0)
  1231.       goto interperateAtTxtpos;
  1232.     goto execnextline;
  1233.  
  1234.   case KW_GOTO:
  1235.     expression_error = 0;
  1236.     linenum = expression();
  1237.     if(expression_error || *txtpos != NL)
  1238.       goto qhow;
  1239.     current_line = findline();
  1240.     goto execline;
  1241.  
  1242.   case KW_GOSUB:
  1243.     goto gosub;
  1244.   case KW_RETURN:
  1245.     goto gosub_return;
  1246.   case KW_REM:
  1247.   case KW_QUOTE:
  1248.     goto execnextline;  // Ignore line completely
  1249.   case KW_FOR:
  1250.     goto forloop;
  1251.   case KW_INPUT:
  1252.     goto input;
  1253.   case KW_PRINT:
  1254.   case KW_QMARK:
  1255.     goto print;
  1256.   case KW_POKE:
  1257.     goto poke;
  1258.   case KW_END:
  1259.   case KW_STOP:
  1260.     // This is the easy way to end - set the current line to the end of program attempt to run it
  1261.     if(txtpos[0] != NL)
  1262.       goto qwhat;
  1263.     current_line = program_end;
  1264.     goto execline;
  1265.   case KW_BYE:
  1266.     // Leave the basic interperater
  1267.     return;
  1268.  
  1269.   case KW_AWRITE:  // AWRITE <pin>, HIGH|LOW
  1270.     isDigital = false;
  1271.     goto awrite;
  1272.   case KW_DWRITE:  // DWRITE <pin>, HIGH|LOW
  1273.     isDigital = true;
  1274.     goto dwrite;
  1275.  
  1276.   case KW_RSEED:
  1277.     goto rseed;
  1278.  
  1279. #ifdef ENABLE_TONES
  1280.   case KW_TONEW:
  1281.     alsoWait = true;
  1282.   case KW_TONE:
  1283.     goto tonegen;
  1284.   case KW_NOTONE:
  1285.     goto tonestop;
  1286. #endif
  1287.  
  1288. #ifdef ARDUINO
  1289. #ifdef ENABLE_EEPROM
  1290.   case KW_EFORMAT:
  1291.     goto eformat;
  1292.   case KW_ESAVE:
  1293.     goto esave;
  1294.   case KW_ELOAD:
  1295.     goto eload;
  1296.   case KW_ELIST:
  1297.     goto elist;
  1298.   case KW_ECHAIN:
  1299.     goto echain;
  1300. #endif
  1301. #endif
  1302.  
  1303.   case KW_DEFAULT:
  1304.     goto assignment;
  1305.   default:
  1306.     break;
  1307.   }
  1308.  
  1309. execnextline:
  1310.   if(current_line == NULL)      // Processing direct commands?
  1311.     goto prompt;
  1312.   current_line +=    current_line[sizeof(LINENUM)];
  1313.  
  1314. execline:
  1315.   if(current_line == program_end) // Out of lines to run
  1316.     goto warmstart;
  1317.   txtpos = current_line+sizeof(LINENUM)+sizeof(char);
  1318.   goto interperateAtTxtpos;
  1319.  
  1320. #ifdef ARDUINO
  1321. #ifdef ENABLE_EEPROM
  1322. elist:
  1323.   {
  1324.     int i;
  1325.     for( i = 0 ; i < (E2END +1) ; i++ )
  1326.     {
  1327.       val = EEPROM.read( i );
  1328.  
  1329.       if( val == '\0' ) {
  1330.         goto execnextline;
  1331.       }
  1332.  
  1333.       if( ((val < ' ') || (val  > '~')) && (val != NL) && (val != CR))  {
  1334.         outchar( '?' );
  1335.       }
  1336.       else {
  1337.         outchar( val );
  1338.       }
  1339.     }
  1340.   }
  1341.   goto execnextline;
  1342.  
  1343. eformat:
  1344.   {
  1345.     for( int i = 0 ; i < E2END ; i++ )
  1346.     {
  1347.       if( (i & 0x03f) == 0x20 ) outchar( '.' );
  1348.       EEPROM.write( i, 0 );
  1349.     }
  1350.     outchar( LF );
  1351.   }
  1352.   goto execnextline;
  1353.  
  1354. esave:
  1355.   {
  1356.     outStream = kStreamEEProm;
  1357.     eepos = 0;
  1358.  
  1359.     // copied from "List"
  1360.     list_line = findline();
  1361.     while(list_line != program_end) {
  1362.       printline();
  1363.     }
  1364.     outchar('\0');
  1365.  
  1366.     // go back to standard output, close the file
  1367.     outStream = kStreamSerial;
  1368.    
  1369.     goto warmstart;
  1370.   }
  1371.  
  1372.  
  1373. echain:
  1374.   runAfterLoad = true;
  1375.  
  1376. eload:
  1377.   // clear the program
  1378.   program_end = program_start;
  1379.  
  1380.   // load from a file into memory
  1381.   eepos = 0;
  1382.   inStream = kStreamEEProm;
  1383.   inhibitOutput = true;
  1384.   goto warmstart;
  1385. #endif /* ENABLE_EEPROM */
  1386. #endif
  1387.  
  1388. input:
  1389.   {
  1390.     unsigned char var;
  1391.     int value;
  1392.     ignore_blanks();
  1393.     if(*txtpos < 'A' || *txtpos > 'Z')
  1394.       goto qwhat;
  1395.     var = *txtpos;
  1396.     txtpos++;
  1397.     ignore_blanks();
  1398.     if(*txtpos != NL && *txtpos != ':')
  1399.       goto qwhat;
  1400. inputagain:
  1401.     tmptxtpos = txtpos;
  1402.     getln( '?' );
  1403.     toUppercaseBuffer();
  1404.     txtpos = program_end+sizeof(unsigned short);
  1405.     ignore_blanks();
  1406.     expression_error = 0;
  1407.     value = expression();
  1408.     if(expression_error)
  1409.       goto inputagain;
  1410.     ((short int *)variables_begin)[var-'A'] = value;
  1411.     txtpos = tmptxtpos;
  1412.  
  1413.     goto run_next_statement;
  1414.   }
  1415.  
  1416. forloop:
  1417.   {
  1418.     unsigned char var;
  1419.     short int initial, step, terminal;
  1420.     ignore_blanks();
  1421.     if(*txtpos < 'A' || *txtpos > 'Z')
  1422.       goto qwhat;
  1423.     var = *txtpos;
  1424.     txtpos++;
  1425.     ignore_blanks();
  1426.     if(*txtpos != '=')
  1427.       goto qwhat;
  1428.     txtpos++;
  1429.     ignore_blanks();
  1430.  
  1431.     expression_error = 0;
  1432.     initial = expression();
  1433.     if(expression_error)
  1434.       goto qwhat;
  1435.  
  1436.     scantable(to_tab);
  1437.     if(table_index != 0)
  1438.       goto qwhat;
  1439.  
  1440.     terminal = expression();
  1441.     if(expression_error)
  1442.       goto qwhat;
  1443.  
  1444.     scantable(step_tab);
  1445.     if(table_index == 0)
  1446.     {
  1447.       step = expression();
  1448.       if(expression_error)
  1449.         goto qwhat;
  1450.     }
  1451.     else
  1452.       step = 1;
  1453.     ignore_blanks();
  1454.     if(*txtpos != NL && *txtpos != ':')
  1455.       goto qwhat;
  1456.  
  1457.  
  1458.     if(!expression_error && *txtpos == NL)
  1459.     {
  1460.       struct stack_for_frame *f;
  1461.       if(sp + sizeof(struct stack_for_frame) < stack_limit)
  1462.         goto qsorry;
  1463.  
  1464.       sp -= sizeof(struct stack_for_frame);
  1465.       f = (struct stack_for_frame *)sp;
  1466.       ((short int *)variables_begin)[var-'A'] = initial;
  1467.       f->frame_type = STACK_FOR_FLAG;
  1468.       f->for_var = var;
  1469.       f->terminal = terminal;
  1470.       f->step     = step;
  1471.       f->txtpos   = txtpos;
  1472.       f->current_line = current_line;
  1473.       goto run_next_statement;
  1474.     }
  1475.   }
  1476.   goto qhow;
  1477.  
  1478. gosub:
  1479.   expression_error = 0;
  1480.   linenum = expression();
  1481.   if(!expression_error && *txtpos == NL)
  1482.   {
  1483.     struct stack_gosub_frame *f;
  1484.     if(sp + sizeof(struct stack_gosub_frame) < stack_limit)
  1485.       goto qsorry;
  1486.  
  1487.     sp -= sizeof(struct stack_gosub_frame);
  1488.     f = (struct stack_gosub_frame *)sp;
  1489.     f->frame_type = STACK_GOSUB_FLAG;
  1490.     f->txtpos = txtpos;
  1491.     f->current_line = current_line;
  1492.     current_line = findline();
  1493.     goto execline;
  1494.   }
  1495.   goto qhow;
  1496.  
  1497. next:
  1498.   // Fnd the variable name
  1499.   ignore_blanks();
  1500.   if(*txtpos < 'A' || *txtpos > 'Z')
  1501.     goto qhow;
  1502.   txtpos++;
  1503.   ignore_blanks();
  1504.   if(*txtpos != ':' && *txtpos != NL)
  1505.     goto qwhat;
  1506.  
  1507. gosub_return:
  1508.   // Now walk up the stack frames and find the frame we want, if present
  1509.   tempsp = sp;
  1510.   while(tempsp < program+sizeof(program)-1)
  1511.   {
  1512.     switch(tempsp[0])
  1513.     {
  1514.     case STACK_GOSUB_FLAG:
  1515.       if(table_index == KW_RETURN)
  1516.       {
  1517.         struct stack_gosub_frame *f = (struct stack_gosub_frame *)tempsp;
  1518.         current_line    = f->current_line;
  1519.         txtpos          = f->txtpos;
  1520.         sp += sizeof(struct stack_gosub_frame);
  1521.         goto run_next_statement;
  1522.       }
  1523.       // This is not the loop you are looking for... so Walk back up the stack
  1524.       tempsp += sizeof(struct stack_gosub_frame);
  1525.       break;
  1526.     case STACK_FOR_FLAG:
  1527.       // Flag, Var, Final, Step
  1528.       if(table_index == KW_NEXT)
  1529.       {
  1530.         struct stack_for_frame *f = (struct stack_for_frame *)tempsp;
  1531.         // Is the the variable we are looking for?
  1532.         if(txtpos[-1] == f->for_var)
  1533.         {
  1534.           short int *varaddr = ((short int *)variables_begin) + txtpos[-1] - 'A';
  1535.           *varaddr = *varaddr + f->step;
  1536.           // Use a different test depending on the sign of the step increment
  1537.           if((f->step > 0 && *varaddr <= f->terminal) || (f->step < 0 && *varaddr >= f->terminal))
  1538.           {
  1539.             // We have to loop so don't pop the stack
  1540.             txtpos = f->txtpos;
  1541.             current_line = f->current_line;
  1542.             goto run_next_statement;
  1543.           }
  1544.           // We've run to the end of the loop. drop out of the loop, popping the stack
  1545.           sp = tempsp + sizeof(struct stack_for_frame);
  1546.           goto run_next_statement;
  1547.         }
  1548.       }
  1549.       // This is not the loop you are looking for... so Walk back up the stack
  1550.       tempsp += sizeof(struct stack_for_frame);
  1551.       break;
  1552.     default:
  1553.       //printf("Stack is stuffed!\n");
  1554.       goto warmstart;
  1555.     }
  1556.   }
  1557.   // Didn't find the variable we've been looking for
  1558.   goto qhow;
  1559.  
  1560. assignment:
  1561.   {
  1562.     short int value;
  1563.     short int *var;
  1564.  
  1565.     if(*txtpos < 'A' || *txtpos > 'Z')
  1566.       goto qhow;
  1567.     var = (short int *)variables_begin + *txtpos - 'A';
  1568.     txtpos++;
  1569.  
  1570.     ignore_blanks();
  1571.  
  1572.     if (*txtpos != '=')
  1573.       goto qwhat;
  1574.     txtpos++;
  1575.     ignore_blanks();
  1576.     expression_error = 0;
  1577.     value = expression();
  1578.     if(expression_error)
  1579.       goto qwhat;
  1580.     // Check that we are at the end of the statement
  1581.     if(*txtpos != NL && *txtpos != ':')
  1582.       goto qwhat;
  1583.     *var = value;
  1584.   }
  1585.   goto run_next_statement;
  1586. poke:
  1587.   {
  1588.     short int value;
  1589.     unsigned char *address;
  1590.  
  1591.     // Work out where to put it
  1592.     expression_error = 0;
  1593.     value = expression();
  1594.     if(expression_error)
  1595.       goto qwhat;
  1596.     address = (unsigned char *)value;
  1597.  
  1598.     // check for a comma
  1599.     ignore_blanks();
  1600.     if (*txtpos != ',')
  1601.       goto qwhat;
  1602.     txtpos++;
  1603.     ignore_blanks();
  1604.  
  1605.     // Now get the value to assign
  1606.     expression_error = 0;
  1607.     value = expression();
  1608.     if(expression_error)
  1609.       goto qwhat;
  1610.     //printf("Poke %p value %i\n",address, (unsigned char)value);
  1611.     // Check that we are at the end of the statement
  1612.     if(*txtpos != NL && *txtpos != ':')
  1613.       goto qwhat;
  1614.   }
  1615.   goto run_next_statement;
  1616.  
  1617. list:
  1618.   linenum = testnum(); // Retuns 0 if no line found.
  1619.  
  1620.   // Should be EOL
  1621.   if(txtpos[0] != NL)
  1622.     goto qwhat;
  1623.  
  1624.   // Find the line
  1625.   list_line = findline();
  1626.   while(list_line != program_end)
  1627.     printline();
  1628.   goto warmstart;
  1629.  
  1630. print:
  1631.   // If we have an empty list then just put out a NL
  1632.   if(*txtpos == ':' )
  1633.   {
  1634.     line_terminator();
  1635.     txtpos++;
  1636.     goto run_next_statement;
  1637.   }
  1638.   if(*txtpos == NL)
  1639.   {
  1640.     goto execnextline;
  1641.   }
  1642.  
  1643.   while(1)
  1644.   {
  1645.     ignore_blanks();
  1646.     if(print_quoted_string())
  1647.     {
  1648.       ;
  1649.     }
  1650.     else if(*txtpos == '"' || *txtpos == '\'')
  1651.       goto qwhat;
  1652.     else
  1653.     {
  1654.       short int e;
  1655.       expression_error = 0;
  1656.       e = expression();
  1657.       if(expression_error)
  1658.         goto qwhat;
  1659.       printnum(e);
  1660.     }
  1661.  
  1662.     // At this point we have three options, a comma or a new line
  1663.     if(*txtpos == ',')
  1664.       txtpos++; // Skip the comma and move onto the next
  1665.     else if(txtpos[0] == ';' && (txtpos[1] == NL || txtpos[1] == ':'))
  1666.     {
  1667.       txtpos++; // This has to be the end of the print - no newline
  1668.       break;
  1669.     }
  1670.     else if(*txtpos == NL || *txtpos == ':')
  1671.     {
  1672.       line_terminator();    // The end of the print statement
  1673.       break;
  1674.     }
  1675.     else
  1676.       goto qwhat;  
  1677.   }
  1678.   goto run_next_statement;
  1679.  
  1680. mem:
  1681.   // memory free
  1682.   printnum(variables_begin-program_end);
  1683.   printmsg(memorymsg);
  1684. #ifdef ARDUINO
  1685. #ifdef ENABLE_EEPROM
  1686.   {
  1687.     // eprom size
  1688.     printnum( E2END+1 );
  1689.     printmsg( eeprommsg );
  1690.    
  1691.     // figure out the memory usage;
  1692.     val = ' ';
  1693.     int i;  
  1694.     for( i=0 ; (i<(E2END+1)) && (val != '\0') ; i++ ) {
  1695.       val = EEPROM.read( i );    
  1696.     }
  1697.     printnum( (E2END +1) - (i-1) );
  1698.    
  1699.     printmsg( eepromamsg );
  1700.   }
  1701. #endif /* ENABLE_EEPROM */
  1702. #endif /* ARDUINO */
  1703.   goto run_next_statement;
  1704.  
  1705.  
  1706.   /*************************************************/
  1707.  
  1708. #ifdef ARDUINO
  1709. awrite: // AWRITE <pin>,val
  1710. dwrite:
  1711.   {
  1712.     short int pinNo;
  1713.     short int value;
  1714.     unsigned char *txtposBak;
  1715.  
  1716.     // Get the pin number
  1717.     expression_error = 0;
  1718.     pinNo = expression();
  1719.     if(expression_error)
  1720.       goto qwhat;
  1721.  
  1722.     // check for a comma
  1723.     ignore_blanks();
  1724.     if (*txtpos != ',')
  1725.       goto qwhat;
  1726.     txtpos++;
  1727.     ignore_blanks();
  1728.  
  1729.  
  1730.     txtposBak = txtpos;
  1731.     scantable(highlow_tab);
  1732.     if(table_index != HIGHLOW_UNKNOWN)
  1733.     {
  1734.       if( table_index <= HIGHLOW_HIGH ) {
  1735.         value = 1;
  1736.       }
  1737.       else {
  1738.         value = 0;
  1739.       }
  1740.     }
  1741.     else {
  1742.  
  1743.       // and the value (numerical)
  1744.       expression_error = 0;
  1745.       value = expression();
  1746.       if(expression_error)
  1747.         goto qwhat;
  1748.     }
  1749.     pinMode( pinNo, OUTPUT );
  1750.     if( isDigital ) {
  1751.       digitalWrite( pinNo, value );
  1752.     }
  1753.     else {
  1754.       //analogWrite( pinNo, value );
  1755.     }
  1756.   }
  1757.   goto run_next_statement;
  1758. #else
  1759. pinmode: // PINMODE <pin>, I/O
  1760. awrite: // AWRITE <pin>,val
  1761. dwrite:
  1762.   goto unimplemented;
  1763. #endif
  1764.  
  1765.   /*************************************************/
  1766. files:
  1767.   // display a listing of files on the device.
  1768.   // version 1: no support for subdirectories
  1769.  
  1770. #ifdef ENABLE_FILEIO
  1771.     cmd_Files();
  1772.   goto warmstart;
  1773. #else
  1774.   goto unimplemented;
  1775. #endif // ENABLE_FILEIO
  1776.  
  1777.  
  1778. chain:
  1779.   runAfterLoad = true;
  1780.  
  1781. load:
  1782.   // clear the program
  1783.   program_end = program_start;
  1784.  
  1785.   // load from a file into memory
  1786. #ifdef ENABLE_FILEIO
  1787.   {
  1788.     unsigned char *filename;
  1789.  
  1790.     // Work out the filename
  1791.     expression_error = 0;
  1792.     filename = filenameWord();
  1793.     if(expression_error)
  1794.       goto qwhat;
  1795.  
  1796. #ifdef ARDUINO
  1797.     // Arduino specific
  1798.     if( !SD.exists( (char *)filename ))
  1799.     {
  1800.       printmsg( sdfilemsg );
  1801.     }
  1802.     else {
  1803.  
  1804.       fp = SD.open( (const char *)filename );
  1805.       inStream = kStreamFile;
  1806.       inhibitOutput = true;
  1807.     }
  1808. #else // ARDUINO
  1809.     // Desktop specific
  1810. #endif // ARDUINO
  1811.     // this will kickstart a series of events to read in from the file.
  1812.  
  1813.   }
  1814.   goto warmstart;
  1815. #else // ENABLE_FILEIO
  1816.   goto unimplemented;
  1817. #endif // ENABLE_FILEIO
  1818.  
  1819.  
  1820.  
  1821. save:
  1822.   // save from memory out to a file
  1823. #ifdef ENABLE_FILEIO
  1824.   {
  1825.     unsigned char *filename;
  1826.  
  1827.     // Work out the filename
  1828.     expression_error = 0;
  1829.     filename = filenameWord();
  1830.     if(expression_error)
  1831.       goto qwhat;
  1832.  
  1833. #ifdef ARDUINO
  1834.     // remove the old file if it exists
  1835.     if( SD.exists( (char *)filename )) {
  1836.       SD.remove( (char *)filename );
  1837.     }
  1838.  
  1839.     // open the file, switch over to file output
  1840.     fp = SD.open( (const char *)filename, FILE_WRITE );
  1841.     outStream = kStreamFile;
  1842.  
  1843.     // copied from "List"
  1844.     list_line = findline();
  1845.     while(list_line != program_end)
  1846.       printline();
  1847.  
  1848.     // go back to standard output, close the file
  1849.     outStream = kStreamSerial;
  1850.  
  1851.     fp.close();
  1852. #else // ARDUINO
  1853.     // desktop
  1854. #endif // ARDUINO
  1855.     goto warmstart;
  1856.   }
  1857. #else // ENABLE_FILEIO
  1858.   goto unimplemented;
  1859. #endif // ENABLE_FILEIO
  1860.  
  1861. rseed:
  1862.   {
  1863.     short int value;
  1864.  
  1865.     //Get the pin number
  1866.     expression_error = 0;
  1867.     value = expression();
  1868.     if(expression_error)
  1869.       goto qwhat;
  1870.  
  1871. #ifdef ARDUINO
  1872.     randomSeed( value );
  1873. #else // ARDUINO
  1874.     srand( value );
  1875. #endif // ARDUINO
  1876.     goto run_next_statement;
  1877.   }
  1878.  
  1879. #ifdef ENABLE_TONES
  1880. tonestop:
  1881.   noTone( kPiezoPin );
  1882.   goto run_next_statement;
  1883.  
  1884. tonegen:
  1885.   {
  1886.     // TONE freq, duration
  1887.     // if either are 0, tones turned off
  1888.     short int freq;
  1889.     short int duration;
  1890.  
  1891.     //Get the frequency
  1892.     expression_error = 0;
  1893.     freq = expression();
  1894.     if(expression_error)
  1895.       goto qwhat;
  1896.  
  1897.     ignore_blanks();
  1898.     if (*txtpos != ',')
  1899.       goto qwhat;
  1900.     txtpos++;
  1901.     ignore_blanks();
  1902.  
  1903.  
  1904.     //Get the duration
  1905.     expression_error = 0;
  1906.     duration = expression();
  1907.     if(expression_error)
  1908.       goto qwhat;
  1909.  
  1910.     if( freq == 0 || duration == 0 )
  1911.       goto tonestop;
  1912.  
  1913.     tone( kPiezoPin, freq, duration );
  1914.     if( alsoWait ) {
  1915.       delay( duration );
  1916.       alsoWait = false;
  1917.     }
  1918.     goto run_next_statement;
  1919.   }
  1920. #endif /* ENABLE_TONES */
  1921. }
  1922.  
  1923. // returns 1 if the character is valid in a filename
  1924. static int isValidFnChar( char c )
  1925. {
  1926.   if( c >= '0' && c <= '9' ) return 1; // number
  1927.   if( c >= 'A' && c <= 'Z' ) return 1; // LETTER
  1928.   if( c >= 'a' && c <= 'z' ) return 1; // letter (for completeness)
  1929.   if( c == '_' ) return 1;
  1930.   if( c == '+' ) return 1;
  1931.   if( c == '.' ) return 1;
  1932.   if( c == '~' ) return 1;  // Window~1.txt
  1933.  
  1934.   return 0;
  1935. }
  1936.  
  1937. unsigned char * filenameWord(void)
  1938. {
  1939.   // SDL - I wasn't sure if this functionality existed above, so I figured i'd put it here
  1940.   unsigned char * ret = txtpos;
  1941.   expression_error = 0;
  1942.  
  1943.   // make sure there are no quotes or spaces, search for valid characters
  1944.   //while(*txtpos == SPACE || *txtpos == TAB || *txtpos == SQUOTE || *txtpos == DQUOTE ) txtpos++;
  1945.   while( !isValidFnChar( *txtpos )) txtpos++;
  1946.   ret = txtpos;
  1947.  
  1948.   if( *ret == '\0' ) {
  1949.     expression_error = 1;
  1950.     return ret;
  1951.   }
  1952.  
  1953.   // now, find the next nonfnchar
  1954.   txtpos++;
  1955.   while( isValidFnChar( *txtpos )) txtpos++;
  1956.   if( txtpos != ret ) *txtpos = '\0';
  1957.  
  1958.   // set the error code if we've got no string
  1959.   if( *ret == '\0' ) {
  1960.     expression_error = 1;
  1961.   }
  1962.  
  1963.   return ret;
  1964. }
  1965.  
  1966. /***************************************************************************/
  1967. static void line_terminator(void)
  1968. {
  1969.   outchar(NL);
  1970.   outchar(CR);
  1971. }
  1972.  
  1973. /***********************************************************/
  1974. void setup()
  1975. {
  1976. #ifdef ARDUINO
  1977.   Serial.begin(kConsoleBaud);   // opens serial port
  1978.   while( !Serial ); // for Leonardo
  1979.  
  1980.   //Serial.println("Keyboard Test:");
  1981.   delay(500);  // avoid garbage into the UART
  1982.   Serial.write("\n\nReset\n");
  1983.  
  1984.   // GPIOs for keyboard CLK and DATA
  1985.   //keyboard.begin(DataPin, IRQpin); //----------------------------------------------------------------------------------------------------------------
  1986.   Keyboard.begin(GPIO_NUM_33, GPIO_NUM_32);
  1987.  
  1988.   // 8 colors
  1989.   //VGAController.begin(GPIO_NUM_22, GPIO_NUM_21, GPIO_NUM_19, GPIO_NUM_18, GPIO_NUM_5);
  1990.   VGAController.begin(GPIO_NUM_2, GPIO_NUM_15, GPIO_NUM_21, GPIO_NUM_17, GPIO_NUM_4);
  1991.      
  1992.   // 64 colors
  1993.   //VGAController.begin(GPIO_NUM_22, GPIO_NUM_21, GPIO_NUM_19, GPIO_NUM_18, GPIO_NUM_5, GPIO_NUM_4, GPIO_NUM_23, GPIO_NUM_15);
  1994.  
  1995.   VGAController.setResolution(VGA_640x350_70HzAlt1, 640, 350);
  1996.  
  1997.   // adjust screen position and size
  1998.   //VGAController.shrinkScreen(5, 0);
  1999.   //VGAController.moveScreen(-1, 0);
  2000.  
  2001.   Terminal.begin();
  2002.   Terminal.connectLocally();      // to use Terminal.read(), available(), etc..
  2003.  
  2004.   Terminal.setBackgroundColor(Color::Black);
  2005.   //Terminal.setForegroundColor(Color::BrightGreen);
  2006.  
  2007.   Terminal.setBackgroundColor(Color::Blue);
  2008.   //Terminal.setForegroundColor(Color::White);
  2009.  
  2010.   Terminal.clear();
  2011.   print_info();
  2012.   //Terminal.setBackgroundColor(Color::Blue);
  2013.   Terminal.setForegroundColor(Color::White);
  2014.  
  2015.   Terminal.enableCursor(true);
  2016.  
  2017.   //Keyboard.reset();
  2018.  
  2019.   printmsg(initmsg);
  2020.  
  2021. #ifdef ENABLE_FILEIO
  2022.   initSD();
  2023.  
  2024. #ifdef ENABLE_AUTORUN
  2025.   if( SD.exists( kAutorunFilename )) {
  2026.     program_end = program_start;
  2027.     fp = SD.open( kAutorunFilename );
  2028.     inStream = kStreamFile;
  2029.     inhibitOutput = true;
  2030.     runAfterLoad = true;
  2031.   }
  2032. #endif /* ENABLE_AUTORUN */
  2033.  
  2034. #endif /* ENABLE_FILEIO */
  2035.  
  2036. #ifdef ENABLE_EEPROM
  2037. #ifdef ENABLE_EAUTORUN
  2038.   // read the first byte of the eeprom. if it's a number, assume it's a program we can load
  2039.   int val = EEPROM.read(0);
  2040.   if( val >= '0' && val <= '9' ) {
  2041.     program_end = program_start;
  2042.     inStream = kStreamEEProm;
  2043.     eepos = 0;
  2044.     inhibitOutput = true;
  2045.     runAfterLoad = true;
  2046.   }
  2047. #endif /* ENABLE_EAUTORUN */
  2048. #endif /* ENABLE_EEPROM */
  2049.  
  2050. #endif /* ARDUINO */
  2051. }
  2052.  
  2053. /***********************************************************/
  2054. static unsigned char breakcheck(void)
  2055. {
  2056. #ifdef ARDUINO
  2057.   if(Serial.available())
  2058.     return Serial.read() == CTRLC;
  2059.   return 0;
  2060. #else
  2061. #ifdef __CONIO__
  2062.   if(kbhit())
  2063.     return getch() == CTRLC;
  2064.   else
  2065. #endif
  2066.     return 0;
  2067. #endif
  2068. }
  2069. /***********************************************************/
  2070. static int inchar()
  2071. {
  2072.   int v;
  2073. #ifdef ARDUINO
  2074.  
  2075.   switch( inStream ) {
  2076.   case( kStreamFile ):
  2077. #ifdef ENABLE_FILEIO
  2078.     v = fp.read();
  2079.     if( v == NL ) v=CR; // file translate
  2080.     if( !fp.available() ) {
  2081.       fp.close();
  2082.       goto inchar_loadfinish;
  2083.     }
  2084.     return v;    
  2085. #else
  2086. #endif
  2087.      break;
  2088.   case( kStreamEEProm ):
  2089. #ifdef ENABLE_EEPROM
  2090. #ifdef ARDUINO
  2091.     v = EEPROM.read( eepos++ );
  2092.     if( v == '\0' ) {
  2093.       goto inchar_loadfinish;
  2094.     }
  2095.     return v;
  2096. #endif
  2097. #else
  2098.     inStream = kStreamSerial;
  2099.     return NL;
  2100. #endif
  2101.      break;
  2102.   case( kStreamSerial ):
  2103.   default:
  2104.     while(1)
  2105.     {
  2106.      
  2107.      //----------- the following is the key modification -------------------------------------------------------------------------------------------------
  2108.      //----------- where the code get the variables from the PS2 keyboard --------------------------------------------------------------------------------
  2109.      //----------- and treat them as the ones from the PC keyboard ---------------------------------------------------------------------------------------
  2110.  
  2111.      /*if (keyboard.available()) {
  2112.        // read the next key
  2113.        char c = keyboard.read();
  2114.        //Serial.print(c);
  2115.        return c;
  2116.      }*/
  2117.      if (Terminal.available()) {
  2118.        // read the next key
  2119.        char c = Terminal.read();
  2120.        //myWrite(c);
  2121.        //Serial.print(c);
  2122.        return c;
  2123.      }
  2124.      //------------ end of modification -------------------------------------------------------------------------------------------------------------------
  2125.      
  2126.      /*if(Serial.available())
  2127.      return Serial.read(); */
  2128.       if(Serial.available()){
  2129.          char c = Serial.read();
  2130.          //vga.print(c); //-------------------------------------------------- così scrive solo i caratteri della tastiera ----------------------------------------------------------------
  2131.          return c;
  2132.       }
  2133.     }
  2134.   }
  2135.  
  2136. inchar_loadfinish:
  2137.   inStream = kStreamSerial;
  2138.   inhibitOutput = false;
  2139.  
  2140.   if( runAfterLoad ) {
  2141.     runAfterLoad = false;
  2142.     triggerRun = true;
  2143.   }
  2144.   return NL; // trigger a prompt.
  2145.  
  2146. #else
  2147.   // otherwise. desktop!
  2148.   int got = getchar();
  2149.  
  2150.   // translation for desktop systems
  2151.   if( got == LF ) got = CR;
  2152.  
  2153.   return got;
  2154. #endif
  2155. }
  2156.  
  2157. /***********************************************************/
  2158. static void outchar(unsigned char c)
  2159. {
  2160.   if( inhibitOutput ) return;
  2161.  
  2162. #ifdef ARDUINO
  2163.   #ifdef ENABLE_FILEIO
  2164.     if( outStream == kStreamFile ) {
  2165.       // output to a file
  2166.       fp.write( c );
  2167.     }
  2168.     else
  2169.   #endif
  2170.   #ifdef ARDUINO
  2171.   #ifdef ENABLE_EEPROM
  2172.     if( outStream == kStreamEEProm ) {
  2173.       EEPROM.write( eepos++, c );
  2174.     }
  2175.     else
  2176.   #endif /* ENABLE_EEPROM */
  2177.   #endif /* ARDUINO */
  2178.     Serial.write(c);
  2179.     Terminal.write(c); //------------------------ here to write to the VGA monitor -----------------------------------
  2180.     myWrite(c);
  2181. #else
  2182.   putchar(c);
  2183. #endif
  2184. }
  2185.  
  2186. /***********************************************************/
  2187. /* SD Card helpers */
  2188.  
  2189. #if ARDUINO && ENABLE_FILEIO
  2190.  
  2191. static int initSD( void )
  2192. {
  2193.   // if the card is already initialized, we just go with it.
  2194.   // there is no support (yet?) for hot-swap of SD Cards. if you need to
  2195.   // swap, pop the card, reset the arduino.)
  2196.  
  2197.   if( sd_is_initialized == true ) return kSD_OK;
  2198.  
  2199.   // due to the way the SD Library works, pin 10 always needs to be
  2200.   // an output, even when your shield uses another line for CS
  2201.   //pinMode(10, OUTPUT); // change this to 53 on a mega
  2202.   pinMode(kSD_CS, OUTPUT); // ------------ è il 5 ---------------------
  2203.  
  2204.   if( !SD.begin( kSD_CS )) {
  2205.     // failed
  2206.     printmsg( sderrormsg );
  2207.     return kSD_Fail;
  2208.   }
  2209.   // success - quietly return 0
  2210.   sd_is_initialized = true;
  2211.  
  2212.   // and our file redirection flags
  2213.   outStream = kStreamSerial;
  2214.   inStream = kStreamSerial;
  2215.   inhibitOutput = false;
  2216.  
  2217.   return kSD_OK;
  2218. }
  2219. #endif
  2220.  
  2221. #if ENABLE_FILEIO
  2222. void cmd_Files( void )
  2223. {
  2224.   File dir = SD.open( "/" );
  2225.   dir.seek(0);
  2226.  
  2227.   while( true ) {
  2228.     File entry = dir.openNextFile();
  2229.     if( !entry ) {
  2230.       entry.close();
  2231.       break;
  2232.     }
  2233.  
  2234.     // common header
  2235.     printmsgNoNL( indentmsg );
  2236.     printmsgNoNL( (const unsigned char *)entry.name() );
  2237.     if( entry.isDirectory() ) {
  2238.       printmsgNoNL( slashmsg );
  2239.     }
  2240.  
  2241.     if( entry.isDirectory() ) {
  2242.       // directory ending
  2243.       for( int i=strlen( entry.name()) ; i<16 ; i++ ) {
  2244.         printmsgNoNL( spacemsg );
  2245.       }
  2246.       printmsgNoNL( dirextmsg );
  2247.     }
  2248.     else {
  2249.       // file ending
  2250.       for( int i=strlen( entry.name()) ; i<17 ; i++ ) {
  2251.         printmsgNoNL( spacemsg );
  2252.       }
  2253.       printUnum( entry.size() );
  2254.     }
  2255.     line_terminator();
  2256.     entry.close();
  2257.   }
  2258.   dir.close();
  2259. }
  2260. #endif
  2261.  
  2262. void myWrite(char c) {
  2263.   if (Terminal.available()) {
  2264.     c = Terminal.read();
  2265.     switch (c) {
  2266.      case 0x7F:       // DEL -> backspace + ESC[K
  2267.        Terminal.write("\b\e[K");
  2268.        break;
  2269.      case 0x0D:       // CR  -> CR + LF
  2270.        Terminal.write("\r\n");
  2271.        break;
  2272.      case 0x03:       // ctrl+c
  2273.        printmsg(breakmsg);
  2274.        current_line = 0;
  2275.        sp = program+sizeof(program);
  2276.        printmsg(okmsg);
  2277.        break;
  2278.      case 0x02:       // ctrl+b
  2279.        Terminal.setForegroundColor(Color::Red);
  2280.        //Terminal.printf("\e[35m");
  2281.        break;
  2282.      case 0x1B:       // ESC
  2283.        //Terminal.write("\r\n");
  2284.        switch (myScreen){
  2285.           case 0:
  2286.              Terminal.setBackgroundColor(Color::Black);
  2287.              Terminal.setForegroundColor(Color::Yellow);
  2288.              myScreen = 1;
  2289.           break;
  2290.           case 1:
  2291.              Terminal.setBackgroundColor(Color::Black);
  2292.              Terminal.setForegroundColor(Color::BrightWhite);
  2293.              myScreen = 2;
  2294.           break;
  2295.           case 2:
  2296.              Terminal.setBackgroundColor(Color::Blue);
  2297.              Terminal.setForegroundColor(Color::White);
  2298.              myScreen = 3;
  2299.           break;
  2300.           case 3:
  2301.              Terminal.setBackgroundColor(Color::Black);
  2302.              Terminal.setForegroundColor(Color::BrightGreen);
  2303.              myScreen = 0;
  2304.           break;
  2305.        }
  2306.        break;
  2307.     default:
  2308.        Terminal.write(c);
  2309.        break;
  2310.     }
  2311.   }
  2312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement