Fórum témák

» Több friss téma
Fórum » Arduino
A klónok CH340 Soros-USB illesztőjének drivere (Letöltés)
Lapozás: OK   205 / 847
(#) CyberLaci hozzászólása Márc 21, 2016 /
 
Sziasztok,
Egy kis segítséget szeretnék kérni rs485 kommunikációban. Most ismerkedem vele. Egy nano klónhoz egy ilyet használok, és a notebookhoz (W8) ilyet.
Az itt lévő master kódot töltöttem fel rá. Ha az arduinoval küldök szöveget, az rendesen átmegy, és a soros monitoron látom is. De ha a laptopról küldöm pl echo ddd > COMX -el az üzenetet egy parancssorban, akkor a nano oldalon nincs semmi.
Mi lehet szerintetek a hiba?
(#) kameleon2 válasza CyberLaci hozzászólására (») Márc 21, 2016 /
 
Adásvezérlést átkapcsoltad?
(#) CyberLaci válasza kameleon2 hozzászólására (») Márc 21, 2016 /
 
Elvileg igen. De semmi...
(#) troby válasza Balázs hozzászólására (») Márc 21, 2016 /
 
Köszönöm szépen, közben lefordítgattam az angol leírását és kiderült, hogy kettőt használ eddig még nem programoztam ilyenre. Köszönöm még egyszer.
(#) szikorapéter hozzászólása Márc 21, 2016 /
 
Üdv ismét. Mostanában böngésztem az internetet (sajnos kevés sikerrel) aztuán ,hogy miként tudok az arduino kisebb programozóiból (arduino nano,arduino uno(328p),arduino mega (2560),arduino due) egy olyan platformot készíteni ami basic interpretert futtat,saját maga kezeli a billentyűzetet és a képi megjelenítést is. Sajnos erre nem igazán találtam választ,bár a due-hoz kaptam egy commodore 64-es forráskódot ,ami 2,2 TFT SPI kijelzőt kezel,csak sajnos szerintem nincs benne a billentyűzetes kezelés. Esetleg valaki ismer ilyen "emulátort" ezekre a programozókra? Sajnos a VGA shield vásárlása esélytelen (az már aranyár kategória számomra) ,viszont még egy szines kis SPI kijelző befért a keretbe. Remélem valakinek van valami ötlete erre a problémára. A válaszokat előre is köszönöm.
(#) troby válasza Balázs hozzászólására (») Márc 22, 2016 /
 
Szia még azt megkérdezném, hogy ennek " TIMSK1|=0x02;"
Mi a szerepe mármint a műveletek tobb helyen lattam es azt írják hibás konkrétan az atmel oldalán is de mások meg azt írjak, hogy működik. Miben másabb ez mint ha csak = jellel átadod az értéket neki?
(#) icserny válasza troby hozzászólására (») Márc 22, 2016 /
 
TIMSK1|=0x02; azt jelenti, hogy TIMSK1= TMSK1 | 0x02;
(#) Balázs válasza troby hozzászólására (») Márc 22, 2016 /
 
Ahogy Icserny mondja, tehát ez az utasítás a regiszternek alulról a második bitjét (OCIE1A) kapcsolja be, a többit érintetlenül hagyja.
(#) vizor válasza szikorapéter hozzászólására (») Márc 22, 2016 /
 
Üdv.

Ha jól értelmezem, billentyűzet kezelést szeretnél. Szerintem a legegyszerűbb egy PS/2-es PC billentyűzet használata, SPI protokollt használ. Hogy könnyebb legyen elindulni, itt egy link a bekötésről és használatáról egy külső Arduino library-val.

Bővebben: Link
(#) troby válasza icserny hozzászólására (») Márc 22, 2016 /
 
Köszönöm, így már értem.
(#) szikorapéter válasza vizor hozzászólására (») Márc 22, 2016 /
 
PS/2-őt már használtam arduinonál. Most ott vagyok bajban hogy nem tudom melyik arduino-m lenne képes elfuttatni a Tiny Basic-et,a PS/2-őt és az SPI TFT 2.2-es (240x320)-as LCD programját. És ott is voltam gondba amikor megpróbáltam több külön programot "összefűzni".
(#) Balázs válasza szikorapéter hozzászólására (») Márc 22, 2016 /
 
A Due, vagyis a rajta lévő 32 bites ARM kontroller egész biztosan alkalmas rá, de hogy Arduino környezetben rendesen ki tudod-e használni az erőforrásait, azt nem tudom. Ha nem Arduino környezetben programoznád, akkor a kijelzőt DMA-val és a PS/2-t megszakításosan kezelve sima ügy lenne. Ilyen feladathoz én a kis 8 bites AVR-eket már nem használnám. Nem tudom, az FPGA-kal mennyire vagy jóban, de ez egy szép FPGA-s projekt lenne. FPGA-ban minden további nélkül tudnál teljes értékű C64 emulátort írni, VGA vagy akár HDMI kimenettel.
(#) szikorapéter válasza Balázs hozzászólására (») Márc 22, 2016 /
 
Leginkább ott vagyok bajban hogy még csak "gyakorlás" szinten tartok a programozással. Ezért próbálok most kész,meglévő programokat egybefűzni.
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 22, 2016 / 1
 
Lehet ardunio alatt is SPI DMA-zni:
ILI9341(new)SPI library for Due supporting DMA transfer(Uno, Mega,.. compatible)
Bővebben: Link

És még meglepően gyorsnak is tünik az LCD kezelése!
(#) szikorapéter válasza kapu48 hozzászólására (») Márc 22, 2016 /
 
Due-ra nem biztos sajnos hogy jó a Tiny Basic amit néztem.
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 22, 2016 /
 
Miért?
Minden Normál arduino utasítást alkalmazhatsz!
Legfeljebb lassabb lessz mintha kihasználnálod az ARM adta plusz HW lehetőségeket!

De valahól elkel kezdeni! Majd idővel az is menni fog.

Bátran belekezdeni! és szépen egymásután megoldani a felmerülő feladatokat.
Csak így lehet bele tanulni!
A hozzászólás módosítva: Márc 22, 2016
(#) mechanika hozzászólása Márc 22, 2016 /
 
Sziasztok!
328P-t lehet használni külső kvarc nélkül?
Ha igen, hogyan kell aktiválni a belső oszcillátort?
A TWI és az UART használható így?
(Arduino)
A hozzászólás módosítva: Márc 22, 2016
(#) Balázs válasza mechanika hozzászólására (») Márc 22, 2016 / 1
 
Lehet, a fuse bitek határozzák meg az órajelforrást. Viszont pontos időzítéseket igénylő aszinkron protokollokhoz (mint az UART) nem javaslom a pontatlan belső oszcillátort.
A hozzászólás módosítva: Márc 22, 2016
(#) doni8 hozzászólása Márc 23, 2016 /
 
Üdv!
Arduino Nano USB-soros illesztőjét lehet használni önmagában? Tehát külső forrásból érkező soros adatot továbbítja a PC fele, a megírt programtól függetlenül? (Nyílván ilyenkor a TX kivezetésre küldöm és a program addig "csendben van", hogy ne zavarjon be)
Realterm programot használom monitorozásra, ha Arduino-val küldök adatokat, akkor tökéletesen megy is, valamint külső eszköz is hiba mentesen fogadja azokat. Viszont Arduino-val fogadni nem tudok külső forrásból (PC felől működik).
Csak a hibakeresés miatt szeretném direktben a soros illesztőt használni.
Azt hiszem az optocsatolós leválasztásnál térdel le a dolog. Mi a tűrés a 0V és 5V-os jelszinteknél?
Wiki szerint:
0 V.....0,8 V alacsony (0)
2,4 V......5 V magas (1)
Ezt a szabályt kell betartani Ardu-nál is?
(#) Kera_Will válasza doni8 hozzászólására (») Márc 23, 2016 /
 
Valami hiányzik a soros kommunikációs eszközeid leírásodból.
A szabványos RS232 soros port az -15- -3 / 3 - 15 V feszültséggel dolgozik a külvilág felé .
Mögötte van egy TTL/RS232 átalakító áramkör.A TTL 1/0 H/L szinteket konvertálja át +/- feszültségre.
Tehát akkor most mit mivel kötsz össze milyen porton milyen feszültség szintekkel?
1 rajz többet mond 1000 szónál.
(#) doni8 válasza Kera_Will hozzászólására (») Márc 23, 2016 /
 
Igaz, egy kicsit hiányos a történet így. Midi üzeneteket küldök és most szeretnék fogadni is. Midi szabvány doksi alapján az Ardunio bemenete le van választva optocsatolóval. Egyenlőre az optocsatoló kimenetét egyből a soros/usb átalakítóra kötném, (amennyiben ez lehetséges), hogy lássam, egyáltalán megérkeznek-e az üzenetek. Az érdekelne, hogy milyen jelszintet kell biztosítani az Arduino vagy az illesztő ic bemenetéhez? Milyen szabványhoz tartozik ez a kommunikáció, ami például a két ic között van? Jelenleg 5V helyett 4,3V-ot mértem, valamint 0V helyett 3V körül, ami biztos nem jó...
(#) szikorapéter válasza kapu48 hozzászólására (») Márc 23, 2016 /
 
Próbáltam egyenlőre csak a TinyBasic és a 2.2-es TFT LCD programját összefűzni. Külön külön mindkettő jó volt,viszont ha együtt próbálom a kettőt használni nem fut le.
A hozzászólás módosítva: Márc 23, 2016
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 23, 2016 /
 
Ilyen kérdést csak úgy lehet érdemben meg tárgyalni, ha linkelnéd az aktuális program lib-eket!

Különben csak nézünk, mint Jani a moziban!
És nem tudjuk, miről beszélsz?

Később kellene látni, hogyan is próbálkoztál?


Végül milyen deszkát választottál?

Installing Additional Arduino Libraries
A hozzászólás módosítva: Márc 23, 2016
(#) szikorapéter válasza kapu48 hozzászólására (») Márc 23, 2016 /
 
Ezt a két könyvtárat használtam,őket próbáltam meg együtt munkára bírni,hogy a basic-em látható legyen az lcd-n.
(#) szikorapéter válasza szikorapéter hozzászólására (») Márc 23, 2016 /
 
Szerintem megvan a hiba. Az EEPROM.h-t dobja be hibának hogy nincs meg,viszont az a baj hogy elvileg ott van a libaries mappában egy EEPROM nevű mappában a többi file-al együtt. Ilyenkor mi a teendő ha a program nem látja a libaries közt a hozzá való file-t?

Hibaüzenetet másolom:
Arduino: 1.6.6 (Windows XP), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

C:\Documents and Settings\Ikaros\Asztal\TinyBasicPlus-master\TinyBasicPlus-master\Arduino\TinyBasicPlus\TinyBasicPlus.ino:156:0: warning: "ARDUINO" redefined [enabled by default]

#define ARDUINO 1

^

<command-line>:0:0: note: this is the location of the previous definition

C:\Documents and Settings\Ikaros\Asztal\TinyBasicPlus-master\TinyBasicPlus-master\Arduino\TinyBasicPlus\TinyBasicPlus.ino:220:48: fatal error: EEPROM.h: No such file or directory

#include <EEPROM.h> /* NOTE: case sensitive */

^

compilation terminated.

exit status 1
Hiba a fordítás során.

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 23, 2016 /
 
Nem tudom nállad mért van ez a hiba?
(Nem is használ EEPROM-ot!, mert Flash memoriában tárolja a dolgait!)

Nálam kevés javítgatás után lefordult hiba nélkül:
Sketch uses 13 694 bytes (5%) of program storage space. Maximum is 253 952 bytes.
Global variables use 7 887 bytes (96%) of dynamic memory, leaving 305 bytes for local variables. Maximum is 8 192 bytes.
Low memory available, stability problems may occur.

Viszont csak 4% szabad RAM terület maradt!

LCD-re írást csak memoria felszabadítás után tudsz be szurni.

Kevés lessz ehez a Mega!
(#) szikorapéter válasza kapu48 hozzászólására (») Márc 23, 2016 /
 
(Nálam az EEPROM.h-ra hivatkozik mint hibaüzenet. A DUE-ra ugyan ez a program rámegy? Most nézem át hogy mi lehet a baj. Esetleg próbáljam meg az eredeti (tvout)-os verzióval? Persze már ha elmegy a due-n a dolog.
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 23, 2016 /
 
Ted megjegyzésbe ezt a sort: 156. #define ARDUINO 1

A Due-ra valami definicios hiba miat nem jó ez a LCD lib!

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


Bele van rakva az LCD lib az *.ino mönyvtárba.
Következő: »»   205 / 847
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem