From 70abf9d5f35370207fb4225d9647071e836d931e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 31 Jan 2014 13:47:39 +0100 Subject: [PATCH 01/29] Remove conioh.h and mygetch.c, these were unused --- src/conio.h | 30 -------------------------- src/mygetch.c | 59 --------------------------------------------------- 2 files changed, 89 deletions(-) delete mode 100644 src/conio.h delete mode 100644 src/mygetch.c diff --git a/src/conio.h b/src/conio.h deleted file mode 100644 index 6b2e2ea..0000000 --- a/src/conio.h +++ /dev/null @@ -1,30 +0,0 @@ -// from http://www.daniweb.com/software-development/c/threads/410155/gcc-equivalent-for-getch -#include -#include -#include -/* reads from keypress, doesn't echo */ -int getch(void) -{ - struct termios oldattr, newattr; - int ch; - tcgetattr( STDIN_FILENO, &oldattr ); - newattr = oldattr; - newattr.c_lflag &= ~( ICANON | ECHO ); - tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); - ch = getchar(); - tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); - return ch; -} -/* reads from keypress, echoes */ -int getche(void) -{ - struct termios oldattr, newattr; - int ch; - tcgetattr( STDIN_FILENO, &oldattr ); - newattr = oldattr; - newattr.c_lflag &= ~( ICANON ); - tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); - ch = getchar(); - tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); - return ch; -} \ No newline at end of file diff --git a/src/mygetch.c b/src/mygetch.c deleted file mode 100644 index 7e7b25e..0000000 --- a/src/mygetch.c +++ /dev/null @@ -1,59 +0,0 @@ -// fromm http://pastebin.com/r6BRYDxV -#include -#include -#include -#include "ctype.h" -#include "setjmp.h" -#include -#include -#include - -int mygetch() { - char ch; - int error; - static struct termios Otty, Ntty; - - fflush(stdout); - tcgetattr(0, &Otty); - Ntty = Otty; - - Ntty.c_iflag = 0; /* input mode */ - Ntty.c_oflag = 0; /* output mode */ - Ntty.c_lflag &= ~ICANON; /* line settings */ - -#if 1 - /* disable echoing the char as it is typed */ - Ntty.c_lflag &= ~ECHO; /* disable echo */ -#else - /* enable echoing the char as it is typed */ - Ntty.c_lflag |= ECHO; /* enable echo */ -#endif - -// Ntty.c_cc[VMIN] = CMIN; /* minimum chars to wait for */ -// Ntty.c_cc[VTIME] = CTIME; /* minimum wait time */ - Ntty.c_cc[VMIN] = 0; /* minimum chars to wait for */ - Ntty.c_cc[VTIME] = 0; /* minimum wait time */ - -//printf("MYGETCH: %d %d", CMIN, CTIME); // 1 0 -//fflush(stdout); - -#if 0 - /* - * use this to flush the input buffer before blocking for new input - */ - #define FLAG TCSAFLUSH -#else - /* - * use this to return a char from the current input buffer, or block if - * no input is waiting. - */ - #define FLAG TCSANOW -#endif - - if ((error = tcsetattr(0, FLAG, &Ntty)) == 0) { - error = read(0, &ch, 1); /* get char from stdin */ - error += tcsetattr(0, FLAG, &Otty); /* restore old settings */ - } - - return (error == 1 ? (int) ch : -1 ); -} From 884003d6a7be559f730aa20b813c475bbdde47a4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 09:38:57 +0100 Subject: [PATCH 02/29] Only add the "baud" function when SOFTWARE_SERIAL_TX is defined The setBaud function used by the "baud" function (e.g., called by func_setBaud) was only defined when SOFTWARE_SERIAL_TX, but the "baud" function was enabled whenever TINY_BUILD was not defined. This caused a compilation failure when SOFTWARE_SERIAL_TX was disabled but TINY_BUILD was not enabled. --- src/bitlash-functions.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bitlash-functions.c b/src/bitlash-functions.c index 6c2074f..2e511a0 100644 --- a/src/bitlash-functions.c +++ b/src/bitlash-functions.c @@ -176,7 +176,7 @@ numvar func_pulsein(void) { reqargs(3); return pulseIn(arg1, arg2, arg3); } numvar func_snooze(void) { reqargs(1); snooze(arg1); return 0; } numvar func_delay(void) { reqargs(1); delay(arg1); return 0; } -#if !defined(TINY_BUILD) +#if defined(SOFTWARE_SERIAL_TX) numvar func_setBaud(void) { reqargs(2); setBaud(arg1, arg2); return 0; } #endif @@ -274,7 +274,9 @@ const prog_char functiondict[] PROGMEM = { "abs\0" "ar\0" "aw\0" +#if defined(SOFTWARE_SERIAL_TX) "baud\0" +#endif "bc\0" "beep\0" "br\0" @@ -351,7 +353,9 @@ const bitlash_function function_table[] PROGMEM = { func_abs, func_ar, func_aw, +#if defined(SOFTWARE_SERIAL_TX) func_setBaud, +#endif func_bitclear, func_beep, func_bitread, From 7bed082a4c173c2e16484fb57e8ed91c2c8f7a80 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 11:30:03 +0100 Subject: [PATCH 03/29] Don't reference find_user_function with TINY_BUILD That function will not be defined, causing a compiler error. To properly fix this, the USER_FUNCTIONS macro is moved from bitlash-functions.c to bitlash.h, so it can be used in bitlash-parser.c as well. --- src/bitlash-functions.c | 7 ------- src/bitlash-parser.c | 2 ++ src/bitlash.h | 6 ++++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/bitlash-functions.c b/src/bitlash-functions.c index 2e511a0..557b7ad 100644 --- a/src/bitlash-functions.c +++ b/src/bitlash-functions.c @@ -387,13 +387,6 @@ const bitlash_function function_table[] PROGMEM = { }; #endif -// Enable USER_FUNCTIONS to include the add_bitlash_function() extension mechanism -// This costs about 256 bytes -// -#if !defined(TINY_BUILD) -#define USER_FUNCTIONS -#endif - #ifdef USER_FUNCTIONS #define MAX_USER_FUNCTIONS 20 // increase this if needed, but keep free() > 200 ish #define USER_FUNCTION_FLAG 0x80 diff --git a/src/bitlash-parser.c b/src/bitlash-parser.c index 30d20a5..9eb15ff 100644 --- a/src/bitlash-parser.c +++ b/src/bitlash-parser.c @@ -612,7 +612,9 @@ void parseid(void) { else if (findpinname(idbuf)) {;} // sym and symval are set in findpinname #endif +#ifdef USER_FUNCTIONS else if (find_user_function(idbuf)) sym = s_nfunct; +#endif else findscript(idbuf); } diff --git a/src/bitlash.h b/src/bitlash.h index 3616d23..ba0b670 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -316,6 +316,12 @@ void beginEthernet(unsigned long baud) { #endif // TINY_BUILD +// Enable USER_FUNCTIONS to include the add_bitlash_function() extension mechanism +// This costs about 256 bytes +// +#if !defined(TINY_BUILD) +#define USER_FUNCTIONS +#endif /////////////////////////////////////////////////////// // From 8d9477d4bbbd0c96ddf4267cd96b7bfa00b4b871 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 15:43:44 +0100 Subject: [PATCH 04/29] Fix use of AVR GPIO registers The previous macros were syntacticaly invalid and caused a compiler warning. Additionally, for targets that have GPIOR0 but not GPIOR1 they would cause compiler errors. This fixes both issues. --- src/bitlash-parser.c | 2 +- src/bitlash.h | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/bitlash-parser.c b/src/bitlash-parser.c index 9eb15ff..2478d5b 100644 --- a/src/bitlash-parser.c +++ b/src/bitlash-parser.c @@ -44,7 +44,7 @@ byte fetchtype; // current script type numvar fetchptr; // pointer to current char in script numvar symval; // value of current numeric expression -#if !USE_GPIORS +#if !defined(USE_GPIORS) byte sym; // current input symbol byte inchar; // Current parser character #endif diff --git a/src/bitlash.h b/src/bitlash.h index ba0b670..542a7bb 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -724,12 +724,8 @@ extern byte fetchtype; // current script type extern numvar fetchptr; // pointer to current char in input buffer extern numvar symval; // value of current numeric expression -#define USE_GPIORS defined(AVR_BUILD) - -#ifndef GPIOR0 || GPIOR1 - #undef USE_GPIORS -#endif -#if (defined USE_GPIORS) +#if defined(AVR_BUILD) && defined(GPIOR0) && defined(GPIOR1) +#define USE_GPIORS #define sym GPIOR0 #define inchar GPIOR1 #else From 43ecc8aea78beb30f83778577f07b0da7f7295d4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 16:02:34 +0100 Subject: [PATCH 05/29] Don't include Arduino.h in bitlash.cpp This is already done in bitlash.h, so this is not needed. However, in bitlash.h we do have to move up the Arduino.h include a bit, because the code that determines the build type depends on CORE_TEENSY, which is defined by Arduino.h when compiling for the Teensy. --- bitlash.cpp | 6 ------ src/bitlash.h | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/bitlash.cpp b/bitlash.cpp index a529a3f..fe3d68c 100644 --- a/bitlash.cpp +++ b/bitlash.cpp @@ -34,12 +34,6 @@ ***/ -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - #ifdef UNIX_BUILD #include "src/bitlash-unix.c" //#else diff --git a/src/bitlash.h b/src/bitlash.h index 542a7bb..b28a942 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -36,6 +36,17 @@ #ifndef _BITLASH_H #define _BITLASH_H +#if defined(HIGH) || defined(ARDUINO) // this detects the Arduino build environment +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" + #define prog_char char PROGMEM + #define prog_uchar char PROGMEM +#else + #include "WProgram.h" + #include "WConstants.h" +#endif +#endif // HIGH || ARDUINO + #if defined(__x86_64__) || defined(__i386__) #define UNIX_BUILD 1 #elif defined(__SAM3X8E__) @@ -127,17 +138,6 @@ // Arduino version: 11 - enable by hand if needed; see bitlash-serial.h //#define ARDUINO_VERSION 11 - -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" - #define prog_char char PROGMEM - #define prog_uchar char PROGMEM -#else - #include "WProgram.h" - #include "WConstants.h" -#endif - - // Enable Software Serial tx support for Arduino // this enables "setbaud(4, 4800); print #4:..." // at a cost of about 400 bytes (for tx only) From 9eff105f70ea63ef865acfd314148084fcf175d1 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 16:11:08 +0100 Subject: [PATCH 06/29] Don't include bitlash-unix.c from bitlash.cpp Since there is a Makefile in src that just compiles the individual source files in src/ which does not need bitlash.cpp at all, it seems pointless to also support compiling the unix build by compiling bitlash.cpp manually. --- bitlash.cpp | 5 ----- src/bitlash.h | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/bitlash.cpp b/bitlash.cpp index fe3d68c..b4ed1bd 100644 --- a/bitlash.cpp +++ b/bitlash.cpp @@ -34,11 +34,6 @@ ***/ -#ifdef UNIX_BUILD -#include "src/bitlash-unix.c" -//#else -//#include "src/bitlash-arduino.c" -#endif #include "src/bitlash-cmdline.c" #include "src/bitlash-eeprom.c" diff --git a/src/bitlash.h b/src/bitlash.h index b28a942..6e75c7d 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -387,7 +387,7 @@ void beginSerial(unsigned long baud) { ; } // Unix build options // (not working) // -// > gcc bitlash.cpp -D UNIX_BUILD +// See README-UNIX.md for info about how to compile // #ifdef UNIX_BUILD #define MINIMUM_FREE_RAM 200 From 6474885d5c75780619aaaa6c74217915ab05db04 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 12:07:05 +0100 Subject: [PATCH 07/29] Rename all source files from .c to .cpp In the Arduino build, they were being compiled as cpp already, since they were included by bitlash.cpp. This makes this fact more clear. In the UNIX build, they were compiled as .c, so this commit temporarily breaks the unix build. --- bitlash.cpp | 24 +++++++++---------- src/{bitlash-api.c => bitlash-api.cpp} | 0 ...itlash-builtins.c => bitlash-builtins.cpp} | 0 ...{bitlash-cmdline.c => bitlash-cmdline.cpp} | 0 src/{bitlash-eeprom.c => bitlash-eeprom.cpp} | 0 src/{bitlash-error.c => bitlash-error.cpp} | 0 ...lash-functions.c => bitlash-functions.cpp} | 0 ...itlash-instream.c => bitlash-instream.cpp} | 0 ...-interpreter.c => bitlash-interpreter.cpp} | 0 src/{bitlash-parser.c => bitlash-parser.cpp} | 0 src/{bitlash-serial.c => bitlash-serial.cpp} | 0 ...{bitlash-taskmgr.c => bitlash-taskmgr.cpp} | 0 ...lash-unix-file.c => bitlash-unix-file.cpp} | 0 src/{bitlash-unix.c => bitlash-unix.cpp} | 0 src/{eeprom.c => eeprom.cpp} | 0 15 files changed, 12 insertions(+), 12 deletions(-) rename src/{bitlash-api.c => bitlash-api.cpp} (100%) rename src/{bitlash-builtins.c => bitlash-builtins.cpp} (100%) rename src/{bitlash-cmdline.c => bitlash-cmdline.cpp} (100%) rename src/{bitlash-eeprom.c => bitlash-eeprom.cpp} (100%) rename src/{bitlash-error.c => bitlash-error.cpp} (100%) rename src/{bitlash-functions.c => bitlash-functions.cpp} (100%) rename src/{bitlash-instream.c => bitlash-instream.cpp} (100%) rename src/{bitlash-interpreter.c => bitlash-interpreter.cpp} (100%) rename src/{bitlash-parser.c => bitlash-parser.cpp} (100%) rename src/{bitlash-serial.c => bitlash-serial.cpp} (100%) rename src/{bitlash-taskmgr.c => bitlash-taskmgr.cpp} (100%) rename src/{bitlash-unix-file.c => bitlash-unix-file.cpp} (100%) rename src/{bitlash-unix.c => bitlash-unix.cpp} (100%) rename src/{eeprom.c => eeprom.cpp} (100%) diff --git a/bitlash.cpp b/bitlash.cpp index b4ed1bd..92de9d1 100644 --- a/bitlash.cpp +++ b/bitlash.cpp @@ -35,15 +35,15 @@ ***/ -#include "src/bitlash-cmdline.c" -#include "src/bitlash-eeprom.c" -#include "src/bitlash-error.c" -#include "src/bitlash-functions.c" -#include "src/bitlash-builtins.c" -#include "src/bitlash-interpreter.c" -#include "src/bitlash-instream.c" -#include "src/bitlash-parser.c" -#include "src/bitlash-serial.c" -#include "src/bitlash-taskmgr.c" -#include "src/bitlash-api.c" -#include "src/eeprom.c" +#include "src/bitlash-cmdline.cpp" +#include "src/bitlash-eeprom.cpp" +#include "src/bitlash-error.cpp" +#include "src/bitlash-functions.cpp" +#include "src/bitlash-builtins.cpp" +#include "src/bitlash-interpreter.cpp" +#include "src/bitlash-instream.cpp" +#include "src/bitlash-parser.cpp" +#include "src/bitlash-serial.cpp" +#include "src/bitlash-taskmgr.cpp" +#include "src/bitlash-api.cpp" +#include "src/eeprom.cpp" diff --git a/src/bitlash-api.c b/src/bitlash-api.cpp similarity index 100% rename from src/bitlash-api.c rename to src/bitlash-api.cpp diff --git a/src/bitlash-builtins.c b/src/bitlash-builtins.cpp similarity index 100% rename from src/bitlash-builtins.c rename to src/bitlash-builtins.cpp diff --git a/src/bitlash-cmdline.c b/src/bitlash-cmdline.cpp similarity index 100% rename from src/bitlash-cmdline.c rename to src/bitlash-cmdline.cpp diff --git a/src/bitlash-eeprom.c b/src/bitlash-eeprom.cpp similarity index 100% rename from src/bitlash-eeprom.c rename to src/bitlash-eeprom.cpp diff --git a/src/bitlash-error.c b/src/bitlash-error.cpp similarity index 100% rename from src/bitlash-error.c rename to src/bitlash-error.cpp diff --git a/src/bitlash-functions.c b/src/bitlash-functions.cpp similarity index 100% rename from src/bitlash-functions.c rename to src/bitlash-functions.cpp diff --git a/src/bitlash-instream.c b/src/bitlash-instream.cpp similarity index 100% rename from src/bitlash-instream.c rename to src/bitlash-instream.cpp diff --git a/src/bitlash-interpreter.c b/src/bitlash-interpreter.cpp similarity index 100% rename from src/bitlash-interpreter.c rename to src/bitlash-interpreter.cpp diff --git a/src/bitlash-parser.c b/src/bitlash-parser.cpp similarity index 100% rename from src/bitlash-parser.c rename to src/bitlash-parser.cpp diff --git a/src/bitlash-serial.c b/src/bitlash-serial.cpp similarity index 100% rename from src/bitlash-serial.c rename to src/bitlash-serial.cpp diff --git a/src/bitlash-taskmgr.c b/src/bitlash-taskmgr.cpp similarity index 100% rename from src/bitlash-taskmgr.c rename to src/bitlash-taskmgr.cpp diff --git a/src/bitlash-unix-file.c b/src/bitlash-unix-file.cpp similarity index 100% rename from src/bitlash-unix-file.c rename to src/bitlash-unix-file.cpp diff --git a/src/bitlash-unix.c b/src/bitlash-unix.cpp similarity index 100% rename from src/bitlash-unix.c rename to src/bitlash-unix.cpp diff --git a/src/eeprom.c b/src/eeprom.cpp similarity index 100% rename from src/eeprom.c rename to src/eeprom.cpp From 5a7c30b89e299e7b1631644ac1ae51fd458ece3d Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 15:26:54 +0100 Subject: [PATCH 08/29] Update the UNIX build Makefile to work with .cpp files This allows the Makefile to compile the code again, though it cannot be compiled correctly yet. --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index a9f182a..8e21dd4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ -all: - gcc -pthread *.c -o bin/bitlash +all: + gcc -lstdc++ -pthread *.cpp -o bin/bitlash install: sudo cp bin/bitlash /usr/local/bin/ From 3f641e34e7adb0efbf3a845f40b31ae170e51ac8 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 12:10:59 +0100 Subject: [PATCH 09/29] Make sure all functions are properly declared Now that we changed the filenames to .cpp, the UNIX_BUILD actually compiles them as C++ instead of C. This means we have to make sure that all functions are properly declared before being used (in C, using a function without a declaration would make the compiler just declare it on the spot, but this is not possible in C++ due to name mangling). Since the regular Arduino build already happened under C++, all the functions needed there were already declared. Additionally, this adds a "mode" parameter to the mkdir call, since that was left out (which didn't cause any compilation errors previously, but probably caused a random undefined value to be passed to mkdir). --- src/bitlash-instream.cpp | 4 +- src/bitlash-unix-file.cpp | 9 +++- src/bitlash-unix.cpp | 5 +- src/bitlash.h | 97 ++++++++++++++++++++++++++------------- 4 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/bitlash-instream.cpp b/src/bitlash-instream.cpp index dad38f0..faffc4d 100644 --- a/src/bitlash-instream.cpp +++ b/src/bitlash-instream.cpp @@ -35,7 +35,7 @@ ***/ #include "bitlash.h" -#if defined(SDFILE) +#if defined(SDFILE) || defined(UNIX_BUILD) #define O_READ 0x01 // from SdFile.h @@ -46,7 +46,7 @@ numvar scriptgetpos(void); byte scriptread(void); byte scriptwrite(char *filename, char *contents, byte append); void scriptwritebyte(byte b); -#elif !defined(UNIX_BUILD) +#else byte scriptfileexists(char *scriptname) { return 0; } #endif diff --git a/src/bitlash-unix-file.cpp b/src/bitlash-unix-file.cpp index 035fd5d..cffefeb 100644 --- a/src/bitlash-unix-file.cpp +++ b/src/bitlash-unix-file.cpp @@ -77,6 +77,11 @@ ***/ #include "bitlash.h" +#include +#include +#include +#include +#include #if defined(UNIX_BUILD) @@ -196,7 +201,7 @@ numvar sdcd(void) { return chdir((char *) getarg(1)); } numvar sdmd(void) { - return mkdir((char *) getarg(1)); + return mkdir((char *) getarg(1), 0777); } numvar exec(void) { @@ -234,4 +239,4 @@ void setup(void) { #endif -#endif // defined(UNIX_BUILD) \ No newline at end of file +#endif // defined(UNIX_BUILD) diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index 4262e39..db106a1 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -27,6 +27,10 @@ OTHER DEALINGS IN THE SOFTWARE. */ #include "bitlash.h" +#include +#include +#include +#include /* @@ -313,7 +317,6 @@ int main () { addBitlashFunction("save", (bitlash_function) &func_save); // from bitlash-unix-file.c - extern bitlash_function exec, sdls, sdexists, sdrm, sdcreate, sdappend, sdcat, sdcd, sdmd, func_pwd; addBitlashFunction("exec", (bitlash_function) &exec); addBitlashFunction("dir", (bitlash_function) &sdls); addBitlashFunction("exists", (bitlash_function) &sdexists); diff --git a/src/bitlash.h b/src/bitlash.h index 6e75c7d..6f77e4b 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -67,30 +67,9 @@ #include "avr/interrupt.h" #endif -#if defined(AVR_BUILD) || defined(ARM_BUILD) -#include "string.h" -#include "ctype.h" -#include "setjmp.h" -#endif - -// Unix includes -#if defined(UNIX_BUILD) -#include -#include -#include #include -#include "ctype.h" -#include "setjmp.h" -#include -#include -#include -//#include -#endif - -#ifndef byte -#define byte uint8_t -#endif - +#include +#include //////////////////////////////////////////////////// // GLOBAL BUILD OPTIONS @@ -398,6 +377,7 @@ void beginSerial(unsigned long baud) { ; } #define E2END 2047 +#define byte uint8_t #define uint8_t unsigned char #define uint32_t unsigned long int #define prog_char char @@ -473,6 +453,11 @@ void doCharacter(char); // pass an input character to the line editor //void flash(unsigned int, int); +///////////////////////////////////////////// +// bitlash-builtins.c +// +void displayBanner(void); +byte findbuiltin(char *name); ///////////////////////////////////////////// // bitlash-arduino.c @@ -496,10 +481,9 @@ void delayMicroseconds(unsigned int); ///////////////////////////////////////////// // bitlash-cmdline.c // -#ifdef TINY_BUILD -byte putlbuf(char); void initlbuf(void); -#endif +void pointToError(void); +void cmd_help(void); // String value buffer size #ifdef AVR_BUILD @@ -565,7 +549,7 @@ void expected(byte); void expectedchar(byte); void unexpected(byte); void missing(byte); -//void oops(int); // fatal exit +void oops(int); // fatal exit ///////////////////////////////////////////// @@ -573,6 +557,8 @@ void missing(byte); // typedef numvar (*bitlash_function)(void); void show_user_functions(void); +char find_user_function(char *id); +void addBitlashFunction(const char *name, bitlash_function func_ptr); void dofunctioncall(byte); numvar func_free(void); @@ -602,6 +588,7 @@ void speol(void); numvar func_printf(void); numvar func_printf_handler(byte,byte); +void cmd_print(void); #ifdef SOFTWARE_SERIAL_TX numvar setBaud(numvar, unumvar); @@ -634,6 +621,7 @@ void stopTask(byte); void startTask(int, numvar); void snooze(unumvar); void showTaskList(void); +unsigned long millisUntilNextTask(void); extern byte background; extern byte curtask; extern byte suspendBackground; @@ -641,15 +629,21 @@ extern byte suspendBackground; ///////////////////////////////////////////// // eeprom.c -// they must live off piste due to aggressive compiler inlining. // +void eewrite(int, byte); +byte eeread(int); +void eraseentry(char *id); +void cmd_function(void); +void cmd_ls(void); +void cmd_peep(void); + #if defined(AVR_BUILD) +// they must live off piste due to aggressive compiler inlining. void eewrite(int, byte) __attribute__((noinline)); byte eeread(int) __attribute__((noinline)); +#endif -#elif defined(ARM_BUILD) -void eewrite(int, byte); -byte eeread(int); +#if defined(ARM_BUILD) extern char virtual_eeprom[]; void eeinit(void); #endif @@ -747,6 +741,47 @@ extern numvar expval; // value of numeric expr or length of string #define IDLEN 12 extern char idbuf[IDLEN+1]; +///////////////////////////////////////////// +// bitlash-instream.c +// + +#if defined(SDFILE) || defined(UNIX_BUILD) +numvar sdwrite(char *filename, char *contents, byte append); +#endif + +///////////////////////////////////////////// +// bitlash-unix-file.c +// +#if defined(UNIX_BUILD) +numvar exec(void); +numvar sdls(void); +numvar sdexists(void); +numvar sdrm(void); +numvar sdcreate(void); +numvar sdappend(void); +numvar sdcat(void); +numvar sdcd(void); +numvar sdmd(void); +numvar func_pwd(void); +#endif + +///////////////////////////////////////////// +// bitlash-unix.c +// +#if defined(UNIX_BUILD) +int serialAvailable(void); +int serialRead(void); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogWrite(byte, int); +void pinMode(uint8_t, uint8_t); +int pulseIn(int, int, int); +unsigned long millis(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int); +#endif + // Strings live in PROGMEM to save ram // From d8f6b1dcfffd1987bbdc2ad920fbc117c46d3c39 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 16:15:44 +0100 Subject: [PATCH 10/29] Explicitely set -DUNIX_BUILD in the Makefile Previously, UNIX_BUILD was automatically set, but this only worked on x86 and x86_64. Since the only point of the Makefile is to do UNIX builds, it might as well set the define explicitely, which could make the code work on other architectures out of the box as well. --- src/Makefile | 4 ++-- src/bitlash-unix.cpp | 5 ++--- src/bitlash.h | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Makefile b/src/Makefile index 8e21dd4..90214bc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ -all: - gcc -lstdc++ -pthread *.cpp -o bin/bitlash +all: + gcc -lstdc++ -DUNIX_BUILD -pthread *.cpp -o bin/bitlash install: sudo cp bin/bitlash /usr/local/bin/ diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index db106a1..65d2354 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -35,9 +35,8 @@ /* Build: - cd bitlash/src - mac: gcc *.c -o bitlash - linux: gcc -pthread *.c -o bitlash + cd bitlash/src + make Issues diff --git a/src/bitlash.h b/src/bitlash.h index 6f77e4b..efd22af 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -47,9 +47,8 @@ #endif #endif // HIGH || ARDUINO -#if defined(__x86_64__) || defined(__i386__) -#define UNIX_BUILD 1 -#elif defined(__SAM3X8E__) +#if !defined(UNIX_BUILD) +#if defined(__SAM3X8E__) #define ARM_BUILD 1 #elif (defined(__MK20DX128__) || defined(__MK20DX256__)) && defined (CORE_TEENSY) // Teensy 3 @@ -59,6 +58,7 @@ #else #define AVR_BUILD 1 #endif +#endif // !defined(UNIX_BUILD) #if defined(AVR_BUILD) From b4a9ac414bfc75c5e7209628747a52d22762cbb7 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 18:03:58 +0100 Subject: [PATCH 11/29] Only enable fprintf and save when SERIAL_OVERRIDE is enabled Their implementations need to override the output function and cannot work without that. --- src/bitlash-instream.cpp | 3 +++ src/bitlash-unix.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/bitlash-instream.cpp b/src/bitlash-instream.cpp index faffc4d..85d27fe 100644 --- a/src/bitlash-instream.cpp +++ b/src/bitlash-instream.cpp @@ -373,6 +373,8 @@ numvar sdwrite(char *filename, char *contents, byte append) { return 1; } +// fprintf needs SERIAL_OVERRIDE to work +#ifdef SERIAL_OVERRIDE ////////// // // func_fprintf(): implementation of fprintf() function @@ -397,5 +399,6 @@ numvar func_fprintf(void) { #endif returntoparsepoint(&fetchmark, 1); } +#endif #endif // SDFILE diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index 65d2354..e182880 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -235,6 +235,7 @@ void fputbyte(byte b) { fwrite(&b, 1, 1, savefd); } +#ifdef SERIAL_OVERRIDE numvar func_save(void) { char *fname = "eeprom"; if (getarg(0) > 0) fname = (char *) getarg(1); @@ -246,6 +247,7 @@ numvar func_save(void) { fclose(savefd); return 1; }; +#endif @@ -313,7 +315,9 @@ int main () { init_fake_eeprom(); addBitlashFunction("system", (bitlash_function) &func_system); addBitlashFunction("exit", (bitlash_function) &func_exit); + #ifdef SERIAL_OVERRIDE addBitlashFunction("save", (bitlash_function) &func_save); + #endif // from bitlash-unix-file.c addBitlashFunction("exec", (bitlash_function) &exec); @@ -326,7 +330,9 @@ int main () { addBitlashFunction("cd", (bitlash_function) &sdcd); addBitlashFunction("md", (bitlash_function) &sdmd); addBitlashFunction("pwd", (bitlash_function) &func_pwd); + #ifdef SERIAL_OVERRIDE addBitlashFunction("fprintf", (bitlash_function) &func_fprintf); + #endif init_millis(); From 41c7ee2c0cd4f6844f60ac93a3a81ea93a634e4a Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 31 Jan 2014 16:41:37 +0100 Subject: [PATCH 12/29] Add a bit more structure to the Makefile This moves more stuff into variables, which makes it easier to selectively change things in the build. --- src/Makefile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index 90214bc..85ebf8b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,12 @@ -all: - gcc -lstdc++ -DUNIX_BUILD -pthread *.cpp -o bin/bitlash +CFLAGS := -DUNIX_BUILD -pthread +LDFLAGS := -lstdc++ -pthread +SOURCES := $(wildcard *.cpp) +BINARY := bin/bitlash +PREFIX := /usr/local +BINPATH := $(PREFIX)/bin + +all: + gcc $(LDFLAGS) $(CFLAGS) $(SOURCES) -o $(BINARY) install: - sudo cp bin/bitlash /usr/local/bin/ + sudo cp $(BINARY) $(BINPATH) From 874c5486098ce8c4167aee2da1a1db4b17a15348 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 5 Feb 2014 10:55:36 +0100 Subject: [PATCH 13/29] Replace char * with const char * where applicable This fixes some compiler warnings that are shown for a UNIX_BUILD, since that build was also converted to C++, but also improves general const-correctness. --- bitlash.h | 8 ++++---- src/bitlash-api.cpp | 2 +- src/bitlash-builtins.cpp | 2 +- src/bitlash-cmdline.cpp | 2 +- src/bitlash-eeprom.cpp | 14 +++++++------- src/bitlash-functions.cpp | 6 +++--- src/bitlash-instream.cpp | 34 +++++++++++++++++----------------- src/bitlash-parser.cpp | 8 ++++---- src/bitlash-serial.cpp | 6 +++--- src/bitlash-unix-file.cpp | 22 +++++++++++----------- src/bitlash-unix.cpp | 8 ++++---- src/bitlash.h | 20 ++++++++++---------- 12 files changed, 66 insertions(+), 66 deletions(-) diff --git a/bitlash.h b/bitlash.h index 1405b44..ac853af 100644 --- a/bitlash.h +++ b/bitlash.h @@ -62,7 +62,7 @@ typedef unsigned long int unumvar; // sometimes unsigned interpretation is bes /////////////////////// // Pass a command to Bitlash for interpretation // -numvar doCommand(char *); // execute a command from your sketch +numvar doCommand(const char *); // execute a command from your sketch void doCharacter(char); // pass an input character to the line editor /////////////////////// @@ -80,8 +80,8 @@ numvar incVar(unsigned char); // increment variable. id is [0..25] for [a..z // // Lookup id and return TRUE if it exists // -byte findscript(char *); // returns TRUE if a script exists with this ID -int getValue(char *key); // return location of macro value in EEPROM or -1 +byte findscript(const char *); // returns TRUE if a script exists with this ID +int getValue(const char *key); // return location of macro value in EEPROM or -1 /////////////////////// // Add a user function to Bitlash @@ -106,5 +106,5 @@ numvar func_printf_handler(byte, byte); // File functions // numvar sdcat(void); -numvar sdwrite(char *filename, char *contents, byte append); +numvar sdwrite(const char *filename, const char *contents, byte append); numvar func_fprintf(void); diff --git a/src/bitlash-api.cpp b/src/bitlash-api.cpp index da829e0..0d4be6f 100644 --- a/src/bitlash-api.cpp +++ b/src/bitlash-api.cpp @@ -45,7 +45,7 @@ jmp_buf env; // // doCommand: main entry point to execute a bitlash command // -numvar doCommand(char *cmd) { +numvar doCommand(const char *cmd) { return execscript(SCRIPT_RAM, (numvar) cmd, 0); } diff --git a/src/bitlash-builtins.cpp b/src/bitlash-builtins.cpp index 5c9c911..dc80669 100644 --- a/src/bitlash-builtins.cpp +++ b/src/bitlash-builtins.cpp @@ -87,7 +87,7 @@ const prog_char builtin_table[] PROGMEM = { -byte findbuiltin(char *name) { +byte findbuiltin(const char *name) { const prog_char *wordlist = builtin_table; while (pgm_read_byte(wordlist)) { diff --git a/src/bitlash-cmdline.cpp b/src/bitlash-cmdline.cpp index 45ac712..6c5a8fc 100644 --- a/src/bitlash-cmdline.cpp +++ b/src/bitlash-cmdline.cpp @@ -125,7 +125,7 @@ byte putlbuf(char c) { void pointToError(void) { if (fetchtype == SCRIPT_RAM) { - int i = (char *) fetchptr - lbuf; + int i = (const char *) fetchptr - lbuf; if ((i < 0) || (i >= LBUFLEN)) return; speol(); while (i-- >= 0) spb('-'); diff --git a/src/bitlash-eeprom.cpp b/src/bitlash-eeprom.cpp index 0283f41..7bb6598 100644 --- a/src/bitlash-eeprom.cpp +++ b/src/bitlash-eeprom.cpp @@ -73,7 +73,7 @@ int findend(int addr) { // return true if string in EEPROM at addr matches string at str -char eestrmatch(int addr, char *str) { +char eestrmatch(int addr, const char *str) { while (*str) if (eeread(addr++) != *str++) return 0; if (eeread(addr) == 0) return 1; // ended at the same place? return 0; @@ -81,7 +81,7 @@ char eestrmatch(int addr, char *str) { // find an entry in the db; return offset of id or FAIL -int findKey(char *id) { +int findKey(const char *id) { int start = STARTDB; while (start < ENDDB-4) { // find the next entry @@ -100,7 +100,7 @@ int start = STARTDB; // Look up an entry by key. Returns -1 on fail else addr of value. -int getValue(char *key) { +int getValue(const char *key) { int kaddr = findKey(key); return (kaddr < 0) ? kaddr : findend(kaddr); } @@ -134,7 +134,7 @@ int starthole = STARTDB, endhole; // // Save string at str to EEPROM at addr -void saveString(int addr, char *str) { +void saveString(int addr, const char *str) { while (*str) eewrite(addr++, *str++); eewrite(addr, 0); } @@ -150,7 +150,7 @@ int erasestr(int addr) { } // erase entry by id -void eraseentry(char *id) { +void eraseentry(const char *id) { int entry = findKey(id); if (entry >= 0) erasestr(erasestr(entry)); } @@ -180,10 +180,10 @@ char id[IDLEN+1]; // buffer for id // fetchptr is on the character after '{' // // BUG: This is broken for file scripts - char *startmark = (char *) fetchptr; // mark first char of macro text + const char *startmark = (const char *) fetchptr; // mark first char of macro text void skipstatement(void); skipstatement(); // gobble it up without executing it - char *endmark = (char *) fetchptr; // and note the char past '}' + const char *endmark = (const char *) fetchptr; // and note the char past '}' // endmark is past the closing '}' - back up and find it do { diff --git a/src/bitlash-functions.cpp b/src/bitlash-functions.cpp index 557b7ad..df0f57e 100644 --- a/src/bitlash-functions.cpp +++ b/src/bitlash-functions.cpp @@ -189,14 +189,14 @@ numvar func_bitread(void) { reqargs(2); return (arg1 & ((numvar)1 << arg2)) != 0 numvar func_bitwrite(void) { reqargs(3); return arg3 ? func_bitset() : func_bitclear(); } numvar func_getkey(void) { - if (getarg(0) > 0) sp((char *) getarg(1)); + if (getarg(0) > 0) sp((const char *) getarg(1)); while (!serialAvailable()) {;} // blocking! return (numvar) serialRead(); } numvar func_getnum(void) { numvar num = 0; - if (getarg(0) > 0) sp((char *) getarg(1)); + if (getarg(0) > 0) sp((const char *) getarg(1)); for (;;) { while (!serialAvailable()) {;} // blocking! int k = serialRead(); @@ -438,7 +438,7 @@ void addBitlashFunction(const char *name, bitlash_function func_ptr) { // find_user_function: find id in the user function table. // return true if found, with the user function token in symval (with USER_FUNCTION_FLAG set) // -char find_user_function(char *id) { +char find_user_function(const char *id) { symval = 0; while (symval < bf_install_count) { if (!strcmp(id, user_functions[symval].name)) { diff --git a/src/bitlash-instream.cpp b/src/bitlash-instream.cpp index 85d27fe..0d69a55 100644 --- a/src/bitlash-instream.cpp +++ b/src/bitlash-instream.cpp @@ -40,14 +40,14 @@ #define O_READ 0x01 // from SdFile.h // Trampolines for the SD library -byte scriptfileexists(char *scriptname); -byte scriptopen(char *scriptname, numvar position, byte flags); +byte scriptfileexists(const char *scriptname); +byte scriptopen(const char *scriptname, numvar position, byte flags); numvar scriptgetpos(void); byte scriptread(void); -byte scriptwrite(char *filename, char *contents, byte append); +byte scriptwrite(const char *filename, const char *contents, byte append); void scriptwritebyte(byte b); #else -byte scriptfileexists(char *scriptname) { return 0; } +byte scriptfileexists(const char *scriptname) { return 0; } #endif // masks for stashing the pointer type in the high nibble @@ -60,7 +60,7 @@ byte scriptfileexists(char *scriptname) { return 0; } #endif // forward declaration -void initparsepoint(byte scripttype, numvar scriptaddress, char *scriptname); +void initparsepoint(byte scripttype, numvar scriptaddress, const char *scriptname); ///////// @@ -72,7 +72,7 @@ void initparsepoint(byte scripttype, numvar scriptaddress, char *scriptname); // and in runBackgroundTasks to kick off the background run. // // -numvar execscript(byte scripttype, numvar scriptaddress, char *scriptname) { +numvar execscript(byte scripttype, numvar scriptaddress, const char *scriptname) { // save parse context parsepoint fetchmark; @@ -137,8 +137,8 @@ numvar execscript(byte scripttype, numvar scriptaddress, char *scriptname) { // how to access the calling and called function names // //#define callername ((char *) ((numvar *) arg[2]) [1]) -#define callername (arg[2] ? (char* ) (((numvar *) arg[2]) [1]) : NULL ) -#define calleename ((char *) arg[1]) +#define callername (arg[2] ? (const char* ) (((numvar *) arg[2]) [1]) : NULL ) +#define calleename ((const char *) arg[1]) ///////// @@ -195,7 +195,7 @@ void markparsepoint(parsepoint *p) { } -void initparsepoint(byte scripttype, numvar scriptaddress, char *scriptname) { +void initparsepoint(byte scripttype, numvar scriptaddress, const char *scriptname) { #ifdef PARSER_TRACE if (trace) { @@ -234,12 +234,12 @@ void initparsepoint(byte scripttype, numvar scriptaddress, char *scriptname) { #ifdef UNIX_BUILD -char *topname = ".top."; +const char *topname = ".top."; void returntoparsepoint(parsepoint *p, byte returntoparent) { // restore parse type and location; for script files, pass name from string pool byte ftype = p->fetchtype; - char *scriptname = calleename; + const char *scriptname = calleename; if (returntoparent) { if ((ftype == SCRIPT_NONE) || (ftype == SCRIPT_RAM)) scriptname = topname; @@ -297,7 +297,7 @@ void fetchc(void) { // void primec(void) { switch (fetchtype) { - case SCRIPT_RAM: inchar = *(char *) fetchptr; break; + case SCRIPT_RAM: inchar = *(const char *) fetchptr; break; case SCRIPT_PROGMEM: inchar = pgm_read_byte(fetchptr); break; case SCRIPT_EEPROM: inchar = eeread((int) fetchptr); break; @@ -327,7 +327,7 @@ void primec(void) { void traceback(void) { numvar *a = arg; while (a) { - sp((char *) (a[1])); speol(); + sp((const char *) (a[1])); speol(); a = (numvar *) (a[2]); } } @@ -340,10 +340,10 @@ numvar *a = arg; // "cat": copy file to serial out // numvar sdcat(void) { - if (!scriptfileexists((char *) getarg(1))) return 0; + if (!scriptfileexists((const char *) getarg(1))) return 0; parsepoint fetchmark; markparsepoint(&fetchmark); - initparsepoint(SCRIPT_FILE, 0L, (char *) getarg(1)); + initparsepoint(SCRIPT_FILE, 0L, (const char *) getarg(1)); while (inchar) { if (inchar == '\n') spb('\r'); spb(inchar); @@ -358,7 +358,7 @@ numvar sdcat(void) { // // sdwrite: write or append a line to a file // -numvar sdwrite(char *filename, char *contents, byte append) { +numvar sdwrite(const char *filename, const char *contents, byte append) { #if !defined(UNIX_BUILD) parsepoint fetchmark; markparsepoint(&fetchmark); @@ -384,7 +384,7 @@ numvar func_fprintf(void) { parsepoint fetchmark; markparsepoint(&fetchmark); - scriptwrite((char *) getarg(1), "", 1); // open the file for append (but append nothing) + scriptwrite((const char *) getarg(1), "", 1); // open the file for append (but append nothing) //serialOutputFunc saved_handler = serial_override_handler; // save previous output handler void scriptwritebyte(byte); diff --git a/src/bitlash-parser.cpp b/src/bitlash-parser.cpp index 2478d5b..df3a9bf 100644 --- a/src/bitlash-parser.cpp +++ b/src/bitlash-parser.cpp @@ -222,7 +222,7 @@ void spush(char c) { } // push a string into the string pool -void strpush(char *ptr) { +void strpush(const char *ptr) { while (*ptr) spush(*ptr++); spush(0); } @@ -383,7 +383,7 @@ const prog_uchar reservedwordtypes[] PROGMEM = { s_arg, s_boot, s_else, s_functi #endif // find id in PROGMEM wordlist. result in symval, return true if found. -byte findindex(char *id, const prog_char *wordlist, byte sorted) { +byte findindex(const char *id, const prog_char *wordlist, byte sorted) { symval = 0; while (pgm_read_byte(wordlist)) { int result = strcmp_P(id, wordlist); @@ -436,7 +436,7 @@ const prog_uchar pinvalues[] PROGMEM = { 0, 1, 13, (PV_ANALOG | 1), (PV_VAR | 25) }; -byte findpinname(char *alias) { +byte findpinname(const char *alias) { if (!findindex(alias, (const prog_char *) pinnames, 0)) return 0; // sets symval byte pin = pgm_read_byte(pinvalues + symval); //sym = (pin & PV_ANALOG) ? s_apin : s_dpin; @@ -624,7 +624,7 @@ void parseid(void) { // // findscript: look up a script, with side effects // -byte findscript(char *idbuf) { +byte findscript(const char *idbuf) { // script function in eeprom? if ((symval=findKey(idbuf)) >= 0) sym = s_script_eeprom; diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index e003335..a77ca09 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -386,7 +386,7 @@ void cmd_print(void) { else if (symval == 'b'-'a') printBinary((unumvar) expval); // :b print binary #endif else if (symval == 'y'-'a') spb(expval); // :y print byte - else if (symval == 's'-'a') sp((char *)expval); // :s print string + else if (symval == 's'-'a') sp((const char *)expval); // :s print string } else if (sym > ' ') while (expval-- > 0) spb(sym); // any litsym else expected(M_pfmts); @@ -422,7 +422,7 @@ numvar func_printf_handler(byte formatarg, byte optionalargs) { // todo: get rid of s_pound if (getarg(0) < formatarg) { speol(); return 0; } - char *fptr = (char *) getarg(formatarg); // format string pointer + const char *fptr = (const char *) getarg(formatarg); // format string pointer while (*fptr) { if (*fptr == '%') { @@ -447,7 +447,7 @@ numvar func_printf_handler(byte formatarg, byte optionalargs) { case 'b': printIntegerInBase(getarg(optionalargs), 2, width, pad); break; // binary case 's': { // string - char *sptr = (char *) getarg(optionalargs); + const char *sptr = (const char *) getarg(optionalargs); // BUG: width is the max not the prepad width -= strlen(sptr); while (width-- > 0) spb(' '); // pre-pad with blanks diff --git a/src/bitlash-unix-file.cpp b/src/bitlash-unix-file.cpp index cffefeb..bd19aaf 100644 --- a/src/bitlash-unix-file.cpp +++ b/src/bitlash-unix-file.cpp @@ -95,7 +95,7 @@ char cachedname[FNAMELEN]; byte cachedflags; // return true iff script exists -byte scriptfileexists(char *scriptname) { +byte scriptfileexists(const char *scriptname) { FILE *file; if ((file = fopen(scriptname, "r")) == NULL) return 0; fclose(file); @@ -111,7 +111,7 @@ byte scriptclose(void) { } // open and set parse location on input file -byte scriptopen(char *scriptname, numvar position, byte flags) { +byte scriptopen(const char *scriptname, numvar position, byte flags) { // open the input file if there is no file open, // or the open file does not match what we want @@ -145,14 +145,14 @@ byte scriptread(void) { return input; } -byte scriptwrite(char *filename, char *contents, byte append) { +byte scriptwrite(const char *filename, const char *contents, byte append) { /// if (scriptfile_is_open) { /// if (!scriptfile.close()) return 0; /// } FILE *outfile; - char *flags; + const char *flags; if (append) flags = "a"; else flags = "w"; @@ -184,28 +184,28 @@ numvar sdls(void) { return 0; } numvar sdexists(void) { - return scriptfileexists((char *) getarg(1)); + return scriptfileexists((const char *) getarg(1)); } numvar sdrm(void) { - return unlink((char *) getarg(1)); + return unlink((const char *) getarg(1)); } numvar sdcreate(void) { - return sdwrite((char *) getarg(1), (char *) getarg(2), 0); + return sdwrite((const char *) getarg(1), (const char *) getarg(2), 0); } numvar sdappend(void) { - return sdwrite((char *) getarg(1), (char *) getarg(2), 1); + return sdwrite((const char *) getarg(1), (const char *) getarg(2), 1); } numvar sdcd(void) { // close any cached open file handle if (scriptfile_is_open) scriptclose(); - return chdir((char *) getarg(1)); + return chdir((const char *) getarg(1)); } numvar sdmd(void) { - return mkdir((char *) getarg(1), 0777); + return mkdir((const char *) getarg(1), 0777); } numvar exec(void) { - return doCommand((char *) getarg(1)); + return doCommand((const char *) getarg(1)); } numvar func_pwd(void) { diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index e182880..1489793 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -237,8 +237,8 @@ void fputbyte(byte b) { #ifdef SERIAL_OVERRIDE numvar func_save(void) { - char *fname = "eeprom"; - if (getarg(0) > 0) fname = (char *) getarg(1); + const char *fname = "eeprom"; + if (getarg(0) > 0) fname = (const char *) getarg(1); savefd = fopen(fname, "w"); if (!savefd) return 0; setOutputHandler(&fputbyte); @@ -277,7 +277,7 @@ void *BackgroundMacroThread(void *threadid) { numvar func_system(void) { - return system((char *) getarg(1)); + return system((const char *) getarg(1)); } numvar func_exit(void) { @@ -346,7 +346,7 @@ int main () { // run the main stdin command loop for (;;) { - char * ret = fgets(lbuf, STRVALLEN, stdin); + const char * ret = fgets(lbuf, STRVALLEN, stdin); if (ret == NULL) break; doCommand(lbuf); initlbuf(); diff --git a/src/bitlash.h b/src/bitlash.h index efd22af..8e3b7bf 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -448,7 +448,7 @@ void connectBitlash(void); // void initBitlash(unsigned long baud); // start up and set baud rate void runBitlash(void); // call this in loop(), frequently -numvar doCommand(char *); // execute a command from your sketch +numvar doCommand(const char *); // execute a command from your sketch void doCharacter(char); // pass an input character to the line editor //void flash(unsigned int, int); @@ -457,7 +457,7 @@ void doCharacter(char); // pass an input character to the line editor // bitlash-builtins.c // void displayBanner(void); -byte findbuiltin(char *name); +byte findbuiltin(const char *name); ///////////////////////////////////////////// // bitlash-arduino.c @@ -501,8 +501,8 @@ extern char lbuf[LBUFLEN]; ///////////////////////////////////////////// // bitlash-eeprom.c // -int findKey(char *key); // return location of macro keyname in EEPROM or -1 -int getValue(char *key); // return location of macro value in EEPROM or -1 +int findKey(const char *key); // return location of macro keyname in EEPROM or -1 +int getValue(const char *key); // return location of macro value in EEPROM or -1 int findoccupied(int); int findend(int); @@ -557,7 +557,7 @@ void oops(int); // fatal exit // typedef numvar (*bitlash_function)(void); void show_user_functions(void); -char find_user_function(char *id); +char find_user_function(const char *id); void addBitlashFunction(const char *name, bitlash_function func_ptr); void dofunctioncall(byte); @@ -632,7 +632,7 @@ extern byte suspendBackground; // void eewrite(int, byte); byte eeread(int); -void eraseentry(char *id); +void eraseentry(const char *id); void cmd_function(void); void cmd_ls(void); void cmd_peep(void); @@ -676,9 +676,9 @@ numvar incVar(uint8_t id); // increment variable. id is [0..25] for [a..z] #define SCRIPT_EEPROM 3 #define SCRIPT_FILE 4 -byte findscript(char *); -byte scriptfileexists(char *); -numvar execscript(byte, numvar, char *); +byte findscript(const char *); +byte scriptfileexists(const char *); +numvar execscript(byte, numvar, const char *); void callscriptfunction(byte, numvar); typedef struct { @@ -746,7 +746,7 @@ extern char idbuf[IDLEN+1]; // #if defined(SDFILE) || defined(UNIX_BUILD) -numvar sdwrite(char *filename, char *contents, byte append); +numvar sdwrite(const char *filename, const char *contents, byte append); #endif ///////////////////////////////////////////// From 0902ccfe254bbed877b4d6a080f87bb70698682f Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 31 Jan 2014 19:19:00 +0100 Subject: [PATCH 14/29] Remove some unused commented code --- src/bitlash-serial.cpp | 4 ---- src/bitlash.h | 21 --------------------- 2 files changed, 25 deletions(-) diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index a77ca09..905e845 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -35,10 +35,6 @@ ***/ #include "bitlash.h" - -// Character io primitives -//#define spb serialWrite - // The default default outpin is, of course, zero #ifndef DEFAULT_OUTPIN #define DEFAULT_OUTPIN 0 diff --git a/src/bitlash.h b/src/bitlash.h index 8e3b7bf..0d7c081 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -451,33 +451,12 @@ void runBitlash(void); // call this in loop(), frequently numvar doCommand(const char *); // execute a command from your sketch void doCharacter(char); // pass an input character to the line editor -//void flash(unsigned int, int); - ///////////////////////////////////////////// // bitlash-builtins.c // void displayBanner(void); byte findbuiltin(const char *name); -///////////////////////////////////////////// -// bitlash-arduino.c -// -//#ifndef ARDUINO_BUILD -#if 0 -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); -void pinMode(uint8_t, uint8_t); -unsigned long millis(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int); -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) -#define INPUT 0 -#define OUTPUT 1 -#endif - - ///////////////////////////////////////////// // bitlash-cmdline.c // From d0202604bff166573254aae653ea145afb20c1c4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 13:01:24 +0100 Subject: [PATCH 15/29] Remove SOFTWARE_SERIAL_RX support This code was broken and unused. If a console on software serial is needed again in the future, the upcoming changes should allow the Arduino SoftwareSerial library to be used. --- src/bitlash-serial.cpp | 101 ----------------------------------------- src/bitlash.h | 2 - 2 files changed, 103 deletions(-) diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index 905e845..d43ede1 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -173,107 +173,6 @@ void speol(void) { spb(13); spb(10); } #endif -/* - bitlash software serial rx implementation adapted from: - SoftwareSerial.cpp - Software serial library - Copyright (c) 2006 David A. Mellis. All right reserved. - hacked by ladyada -*/ -#ifdef SOFTWARE_SERIAL_RX - -#define MAX_SOFT_RX_BUFF 32 -volatile uint8_t soft_rx_buffer_head; -uint8_t soft_rx_buffer_tail; -char soft_rx_buffer[MAX_SOFT_RX_BUFF]; - -// Pin-change interrupt handlers -// -// NOTE: Currently, software rx is supported only on pins d0..d7. -// -//SIGNAL(SIG_PIN_CHANGE0) {} - -#ifdef ARDUINO_BUILD -#define RXPINCHANGEREG PCMSK2 -SIGNAL(SIG_PIN_CHANGE2) { -#else -#define RXPINCHANGEREG PCMSK0 -SIGNAL(PCINT0_vect) { -#endif - if ((RXPIN < 8) && !digitalRead(RXPIN)) { - char c = 0; - int bitdelay = bittime[RXPIN]; - // would be nice to know latency to here - delayMicroseconds(bitdelay >> 1); // wait half a bit to get centered - for (uint8_t i=0; i<8; i++) { - delayMicroseconds(bitdelay); - if (digitalRead(RXPIN)) c |= _BV(i); - } - delayMicroseconds(bitdelay); // fingers in ears for one stop bit - - uint8_t newhead = soft_rx_buffer_head + 1; - if (newhead >= MAX_SOFT_RX_BUFF) newhead = 0; - if (newhead != soft_rx_buffer_tail) { - soft_rx_buffer[soft_rx_buffer_head] = c; - soft_rx_buffer_head = newhead; - } - } -} - -int softSerialRead(void) { - uint8_t c; - if (soft_rx_buffer_tail == soft_rx_buffer_head) return -1; - c = soft_rx_buffer[soft_rx_buffer_tail]; - cli(); // clean increment means less excrement - if (++soft_rx_buffer_tail >= MAX_SOFT_RX_BUFF) soft_rx_buffer_tail = 0; - sei(); - return c; -} - -int softSerialAvailable(void) { - cli(); - uint8_t avail = (soft_rx_buffer_tail != soft_rx_buffer_head); - sei(); - return avail; -} - -void beginSoftSerial(unsigned long baud) { - -#ifdef BAUD_OVERRIDE - baud = BAUD_OVERRIDE; -#endif - // set up the output pin and copy its bit rate - bittime[RXPIN] = setBaud(DEFAULT_OUTPIN, baud); - pinMode(RXPIN, INPUT); // make it an input - digitalWrite(RXPIN, HIGH); // and engage the pullup - delayMicroseconds(bittime[RXPIN]); // gratuitous stop bits - - // Enable the pin-change interrupt for RXPIN - if (RXPIN < 8) { // a PIND pin, PCINT16-23 - RXPINCHANGEREG |= _BV(RXPIN); - PCICR |= _BV(2); - } -#if 0 - // for pins above 7: enable these, set up a signal handler above, - // and off you go. - else if (RXPIN <= 13) { // a PINB pin, PCINT0-5 - PCMSK0 |= _BV(RXPIN-8); - PCICR |= _BV(0); - } - else if (RXPIN < 23) { // a PINC pin, PCINT8-14 - PCMSK1 |= _BV(RXPIN-14); - PCICR != _BV(1) - } -#endif - else unexpected(M_number); - // todo: handle a0..7; pin out of range; extend for Sanguino, Mega, ... -} - -// aliases for the rest of the interpreter -#define serialAvailable softSerialAvailable -#define serialRead softSerialRead -#define beginSerial beginSoftSerial - -#endif // SOFTWARE_SERIAL_RX - #if (defined(ARDUINO_BUILD) && (ARDUINO_VERSION >= 12)) || defined(AVROPENDOUS_BUILD) || defined(UNIX_BUILD) // From Arduino 0011/wiring_serial.c diff --git a/src/bitlash.h b/src/bitlash.h index 0d7c081..cb5a423 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -62,9 +62,7 @@ #if defined(AVR_BUILD) -#include "avr/io.h" #include "avr/pgmspace.h" -#include "avr/interrupt.h" #endif #include From c96a55ff5a935381c6f0c3b0497ddf6b2c2aa5fd Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 17:14:50 +0100 Subject: [PATCH 16/29] Remove support for the Adafruit ethernet shield It seems this relied on software serial reception, which was broken and removed. In the future, it should be possible to re-add support by just passing in a SoftwareSerial instance. Additionally, all ethernet examples now use the output handler feature instead of relying on the bitlash library itself to know how to talk to the Ethernet library or hardware. --- src/bitlash.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/bitlash.h b/src/bitlash.h index cb5a423..32a9f24 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -139,12 +139,6 @@ // Enable WIZ_ETHERNET true to build for telnet access to the official Arduino // WIZ-5100 Ethernet shield //#define WIZ_ETHERNET 1 -// -// Enable AF_ETHERNET to build for telnet access to the Adafruit Ethernet shield -// configured per the pinout below -// -//#define AF_ETHERNET 1 -// /////////////////////////////////////////////////////// // WIZNET ETHERNET CONFIGURATION @@ -176,19 +170,6 @@ void beginEthernet(unsigned long baud) { #endif // WIZ_ETHERNET -/////////////////////////////////////////////////////// -// ADAFRUIT XPORT ETHERNET CONFIGURATION -// -#ifdef AF_ETHERNET -#define NET_TX 2 -#define NET_RX 3 -#define SOFTWARE_SERIAL_RX 1 -#define RXPIN NET_RX -#undef HARDWARE_SERIAL_TX // sorry, no room for pin 0/1 hard uart -#define DEFAULT_OUTPIN NET_TX -#define BAUD_OVERRIDE 9600 -#endif // AF_ETHERNET - /////////////////////////////////////////////////////// From 1af516522d1bdb111ad9221e63ecd7902dd1172f Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 17:17:29 +0100 Subject: [PATCH 17/29] Remove ethernet shield support In the future, it should be possible to just pass in an ethernet client Stream object and leave all the ethernet initialization stuff where it belongs. Additionally, all ethernet examples now use the output handler feature instead of relying on the bitlash library itself to know how to talk to the Ethernet library or hardware. --- src/bitlash.h | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/bitlash.h b/src/bitlash.h index 32a9f24..61fab83 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -130,48 +130,6 @@ #endif // HIGH: arduino build -/////////////////////////////////////////////////////// -// -// ARDUINO ETHERNET BUILD OPTIONS -// -/////////////////////////////////////////////////////// -// -// Enable WIZ_ETHERNET true to build for telnet access to the official Arduino -// WIZ-5100 Ethernet shield -//#define WIZ_ETHERNET 1 - -/////////////////////////////////////////////////////// -// WIZNET ETHERNET CONFIGURATION -// -#ifdef WIZ_ETHERNET - -// -// You'll need these two lines in your sketch, as of Arduino-0022: -// -// #include -// #include -// - -byte mac[] = { 'b','i','t','l','s','h' }; -byte ip[] = { 192, 168, 1, 27 }; -byte gateway[] = { 192, 168, 1, 1 }; -byte subnet[] = {255,255,255,0}; -#define PORT 8080 -Server server = Server(PORT); - -#define beginSerial beginEthernet -#define serialAvailable server.available -#define serialRead server.available().read -#define serialWrite server.write -void beginEthernet(unsigned long baud) { - Ethernet.begin(mac, ip, gateway, subnet); - server.begin(); -} -#endif // WIZ_ETHERNET - - - - /////////////////////////////////////////////////////// // // SANGUINO BUILD From 82436717feefdcbf4a2f1dadc0354834d7d98449 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 7 Feb 2014 17:59:45 +0100 Subject: [PATCH 18/29] Remove unused function declarations These functions were declared for AVROPENDOUS, but no logner used. The use of connectBitlash was removed in 357fd6f, the use of usbMoueOn and usbMouseOff was removed in 024c56944. --- src/bitlash.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/bitlash.h b/src/bitlash.h index 61fab83..278836e 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -371,9 +371,6 @@ typedef unsigned int unumvar; uint8_t usbAvailable(void); int usbRead(void); void usbWrite(uint8_t); -void usbMouseOn(void); -void usbMouseOff(void); -void connectBitlash(void); #endif // avropendous From b387c9c02b83ca2af5919626f60bf69da4152afc Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 7 Feb 2014 17:15:36 +0100 Subject: [PATCH 19/29] Clean up support for older Arduino versions Now, src/bitlash.h requires that either ARDUINO or UNIX_BUILD is defined. If this is not the case, compilation fails with an error. Arduino versions below 018 did not define the ARDUINO variable. This means that for those versions, the user must manually set the Arduino version to make the build work. Furthermore, the ARDUINO_BUILD and ARDUINO_VERSION macros are dropped, since now the ARDUINO variable can just always be used. --- examples/bitlash_rf/bitlash_rf.h | 4 ---- src/bin/bitlash | Bin 63176 -> 54029 bytes src/bitlash-serial.cpp | 2 +- src/bitlash.h | 40 +++++++++++++++---------------- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/examples/bitlash_rf/bitlash_rf.h b/examples/bitlash_rf/bitlash_rf.h index d63de64..ae9e77e 100644 --- a/examples/bitlash_rf/bitlash_rf.h +++ b/examples/bitlash_rf/bitlash_rf.h @@ -57,10 +57,6 @@ //#define RADIO_VIRTUALWIRE //#include "VirtualWire.h" -// Arduino detector -// -#define ARDUINO_BUILD 1 - #include #include #include "pkt.h" diff --git a/src/bin/bitlash b/src/bin/bitlash index 12c529c3cf9e9b886056a11be5a2717c5357d566..8446972c660d6722091bd28fbac435561085f1d1 100755 GIT binary patch literal 54029 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

$li3k z1FPH&J2ucG^$j!Z(pungO}57(_4<7Ma)A!xAvq0n@gJuuq-+@jVx| zAUdZVY0O17YQmNEhVp^+Hk#qgXnovskK z0^Ejfbi#r&4(YcKsiT>iH_=wjZd7B|z%YLoiwz7@8u4`q(u$8BE5z17W!KOanP7T3 zV0MK))l|Xv0H_ARlduL-u188fovvgRwiO^5ZIbUJ2hgg{=0TLi+|0$D#z>8Q>E`V) zGF6r;5FVOEi^fQ5H)lhxY&3oJu0 z{LBvFj1MtFw?L6G89Cahb+)G=U^HA1W!vPn@n~Ah*$TI>`AQtBV>?Bk@G9KSS2S;D zA3f@fmdEk4swW+%;|?jF4^XhKerA1Cmj0bI0L|-Id1T}r#b`TfEN=~$c@zyo!vj#% zV+s6#^>3gaMzL6bG9kNBH?@VOW_}WzWc3}%N05yg(f1$}l@@Y;cpcNm88GPaJRD3) zhubQv2|OG>B}!SE(K#Qgo2M zLFcUI^)|#!=kCu&?ELuFFD{}p6f^uC!H)P+n=&fTqH6x#m5MeCuZY!C3sChhwQ%s! zs^;$qV{MCPrH{}tQbTunfZ^{iQ*~^8FQ<|pFz@(F^A%uAj}&a8%Be-H-n)FN3Z>2p zyx^<*r$q=!!DL-(DYjZM&{tYz89`o?znG`)TSk2=Z_P}Uu!S3`1t)jB36 zqm436IvB*(qaK?9^ku$h*9EPJ8AII;`dV!ZDuK!HLsb;ZIooYJ&&{@NI9r&7zj>Ryv%|TDMy@3^q%O4}1xjAlu|hxq|pn>{oNy>~Y)Yt=rn{xOvBb!f4?b?He` z&x{oa(X3HdK~ZBDebQ8jDxlQ+c!*+sebgEF`1|MhD_wL$EY4|T!QDfL%lU|_vNqhu=^S=}--$p`o1}uI`zIiA+(8l7tc?BBI{zF;>UtIC~yMQm<1Sm4R7h2|Kac1 zbMHsrH217U0jN89l?pnx!Pm_B)j2Y@XxWZFaKN06>@9-`YrTJ9tw;Mx6zVesNoXL1 z>TGoEM-Qs)C5o%g_8NuG_0U)b$U_lO_XuR5t``^VF4UM5-j0G{ptl8o1NdVykNFlO z>{YTh^LNy_nMtfz6xDHxR_LA$SKFOh@n9p$g+}Bw9z`Vym{jdKHR++HCz} zct(b|#Y*OJVr;-tu({LBr5w=VxhdM3xBnZ)XU&PU`csq4B`Cl0XnY31GafcHbog|r zV&x&jmxQrr-d60O*N-3+KnS)QjXYszn>i9nvHqfU8AhafpBf4X>$Rm~RoiStBG&UN zL9t#6N{DaAVV;hwvwckjY}_y>-Sp@erhB{)i1lH2gzu;UVjn{IaH?M5H7z!U#Kyj+ zhIf<+E!#kvpm;3+yDg@LLQ9j)r_iKqQd5oUn!BG9!zn+f+~RY1aFj~%cg*tGW?5OA zgmpL4Y5z*rm2V{bnEjekvj`FC6<=`czJ)X`e))KUHCY-Zqway{%_*5XIvHB%9-O;z z3vEIHRbFS{LrHktvypNs&R5{DGa&YOGNhgsC=YX=BpeKjOGWP>!#oN_G9cBv3hC1s z@T4Bi3go9^eKYvBp>`u{L!V_J&cMRd!&zXOSpi>aV^&~ADqO{hF6o+fwK(V42LE@?>V>JTozK~i%f4jTkTiS0y#DrKY3al5lZreZ`_-k(?Sp;G%iMNnX4dS% zy$9hf%I-nEbC>(vUOR<*H_NQh=PMgGbf_pEQsVZtOPcF;+q0%m&b(@FroEuF-0msL zbC-DC?UH5}m3YV5^V0?o8#c&ApLY8-uJR&!Gd6J7;F|{7hYzzumz`cdZAX#ai||71 zc1g4FUTl}Iv>Z|c?St(D>_hGS?EUQ-_KXSk%k7s>uuqs^?=``mkzv35a(gfP4fekF z750G;9c&*rp{@0N!(EEl3@83B43; z?5$|0ixpjasiGM|j|k0`bgzs2BuVcPx|4--l|GU25$7r|z-^=~qE#K<@%lg(xfB95sis&0BG+*eC!rvqD z&xGocsY!&8%^_1UIG$N#(bKAoxbTsKwG?_%hkDsm4C{qN@Y-%a-yDW6XNidrHs7Q7KeqY7JGVaY(0z~GbMKaiH}>tjV#S0By(SDC zIC${5371c}{PK(m85u)|8tZPW3asC-X>IkI+n+@CQkkU&mYaEnrS?@)q{&#%m-_5( zERDb3qq^`axHK zZUx;6x(D=C(0b5gpz+v_o&`+>?Qyr)b}r;&>+zDpjn{q-LO08OQ4%Ue+GRKwDc9U8)z!-WuF3_ z2-*qH{nUVt0B!RhXgAQ^pesOe|2wo5)C0O7bQkDx(1W0f9Sq}r&{WVHa40?nbk|;# z8}!lFkuRtT`XXq*I^+vl1bPaz3ba#4!#Dyu0<`Y|QrK@&US{OoPm3v|#s zuovimfO5sM$pZmQ$It!LAQc_0QxEDDbVr9 zkiLsyYzG|ydI)qL=$D{A&{LqBL2aKSJ!q#d(9b|`06hzO8)%QNhVeXT2IyCy3qjZ8 zmdFawlD~#R+d+W`S<|2Kj=H`4;vD-2wV4=)Aun zU(h1Zv!HP%^6d^k0h$5Y1#}^34(JNddqKB?J`egT=xd1^O~*rylS>pd&zAH^5$?qd|S3dq6jX`cA-Jpm%_N z0J<0S6zF@Poh~*EdU|&RXu?UP2b~D&10CFm^q`YKUj*FvFKLbTqCBmOA%PU!u_iaT!BssBt%DVW;?as@FLPUv|fxl(o z{}wdNkH3Zmh`$hjFM@x26n|})zXJFr4~0T7OC zyh#50!5;zs&?vSN{q>F&@9e1^!HH`gmu!e5v3+1b%rGzc|dF0{%(xS4Q!d zh57m5XKf3GhFSS4IoEFu_&0!miQ^zna;s|2X)a zuwEKr<(EeIi3ym8z>n1r=_?_9z#nc+U!u}eAM!x|81Rc>=fr-New0wiZAi(e9X-&q z66>|`1nBX!BvOv`;BNu{ek(tIGYe4q9pHC(JQVscihnrFKLq|k@SRpZg>g~(6W}+3 z4>u9Xe?cVwwuxv*@OxYNG88ENAn^YQ{$*BvZX|sc_)Wi(-UI&6zrtS+{@GvQ?*RYb zzrsHRzJc}a5Nr9=FjMshpVq^Jto%ih^0&3YPTLi+#dT@TW)dr-aKt2>iGwWAn4X9{~Q+sPyIG^d9hU0iWj| z-T&Rp=Jr_+el_@4SkvDW;qL(dnO{kN2>chpcUaTk97%ry{13p7iND8s$(lZ1IcDmQTfx5${OTzFI?jOjuY&&?__Lz;Gs661;C~N(K@{J` ze6m9-_+y?4g+4(zakRy6$A6$I0i5zl#Xd9$x!DMZ?GS%uIG-utcl$#qlo`c$g!%d4 zUk<)MieDDyuK|A(_%B8ApAYl5gWqpQ?D=Uw_m!+Hu^I3+}lH3%?O?e(q!DHS`EVIaAtR#Gy5H9Z&6vT#o{4`1!wo7Cknh*XU z@EumZ#V@S^KMVYcR=!&PaDBIfUkrY%d3!(j9`I*a)5oj!<@N{vUhwBd@n?n0pNMmc zH^Gm!E=dLd8}MVT-==_n8vMRi{c4zT`SZd5n|_{+gBu=Z~% z@4|5RWj%C`^fJzUV)ZLJUpfl@UDkZ!*N6K>51b=S$N5k!zn202a`1au(=SxzqX4s0e(LC z^evxoe@W;Y_ETHIFMTx>`pU|ucK$fJo%cho-=0utoi(5MTf*f$4*nhBUt`siFo%_p zof6?__t%6%rHR&Z+?YrTh@T4n1^YuGSCoF$(8Qkt{ygxniQ>-*=bsP$?Z3ib1AZ;| zvG%Xq!T;h{^4|}B&(}ktqNx1y!}%WvzYzRb{eaFZ%fQDmV5A+c;^eCS;OBwg*~*_C z;nVr%b>M?U(yQ$$&m-%R|8(%_wVH{mHaH?}ofK|Jvg3LvNUMwO$9I6g0Q~;ed{i~L zoQJ^A`xX8P@IBzCThn_Y^=OOp)0N==A*!D|$z>$JGYI_F2ScH+oBPS5(SC9sHz0FM@x&l}~=OLg^rw?0F1w7rqtS@1F&K zB=}vd^`-IEF5E2YoCqBw^-wcEK>6JfonIE@HbXAfde#HJ3I5a8a>qZ;O1S;OFMB(- z-FATQ20xZRIt2db;A6Uv*wwNwIsyK{U*WgyWEg)2Kh``u2>fHb6zrGH+@EmD8*?>f?Q`%pWtNB--;zY5{Rr>yNPoeDV1LC+4zeS>&7AM!Jwg}V*ggYMrH zy&t>1J^+6i__6xSDe#NI$8C^EKI+(>^>@O8rV#vC?KJ}YT<}L*)1#bpq)Y8J5B%l7 z!uNr{5&Qwx^p&{zm zD`@YiY_%crj)XhocSatk7rS-A6 znQP;XD$V?z?bbMBt=6*8R&10hEv+x@G{u;P@c&-_Yk~hU3(QV&u&y+rS~0m;x|-7s z3J&AXG>f;D1Z@Skw{via_eKaMx>TI^ip1HNL!SowC{P-cbg@qYZ7qEAH*{$}Uf)ql z@tk-EK5;I?pYZ?ZIXHyD#n;Ao2h$|}#C$JO2?Hh80 z!D|9=S}_;*vxU~Sad1fE%OtML?G(8-LUsQC#=#xTs3au0RkEJrTjVOSj~Fs~ z$ne1<`m2D^0&k?|8AH6wi+!$KP+z&Cg*rsvA1N<0hTwrY_mGK`rVsYH7D;STiGN70 zzsQq67!L℘)2ITWAc)UtR)zisG9b%)#@B-lEcys7N+=<@i&SMMm*XoZ ztV4%y%tJ!t=PEABL%LFAfsY}augW9W>otbt;ma;~JWw0@|B{m5BbTZDixKZY43_{s zR4n|d{jmlvMSy&bPTwQmff&})0@yhg`OyAEBXmY!O`j3(U{;2tr*)L|YMy=ym_NZc z>HKrz9YDx0GcnQ>3HxX52L(20txUdHr`P^^qX3QKZ^@ri-F15HH?ILkB09bH{}nO; zXnzk8zM9+b2B73?b$abz@0N__Njg2hXgN(6gHOI&$F=`9CH+Q8PsJhI>GBI~+$6Y8 zujh+pGC?>+Q0K4H>-w*0mR`?4wUS=XSCqaj{+g%10~pyv&zE|>wzmU_OV7h9rs|-> zL}_hpP45st?vV8KV=UGyMIxGRM%)P zCu`n+w@G?kOuNg$qIOANPDZm_c1xIoPveiuuhVZXb|8lHp<*URsy3{OavzW&lb!gq zrr+gtFuu#n#K;dXlvG@|pNio;6#;8{dc29Q9vhe#_bC$oBw6cq1Q9y_kYN^Hj~UW& zo9EX&PLmill}@kMYpwr_>Ayo-Dw9s1BI}Km|6=-+NJ}Qx>GgW0tEATrqnkmOKLu&% zYQmp2|E{v$>v}h{!{bH8BI8Hv`K4KUyx2al7E^8gzEHTn&DJdx-{*8a5!(~s1G|0 zY+T*7po)gmNtEMy>}ZVXLn`)kFGVi_p}9ueO;?M?cT4#{y+@^UcT!Y;HY<*XTcin8 zx_HMqyaaSAJdD9@XiF2;SHXpD1|q{r|PV z<1qVom2&EFQ^5GS_N3{C^3~@Fi1KwmKI4pY+hrH-3%;xwUd}jX$~*^`#FX-^ z1Kv`39*lwiIR;(_oa#$IAx9UjE9g2RIQ>u?UFy>?>IJ8t^q@;GGky>}D7aq!B*ICv ze!){X70zvdw^aTiG4M$-@VPPYq8K=e*!B>JmnxXJsf;R%UqcxiQjWZ&@tA~;w zBJ%W1GwIjw3z#l=2f@=szPI4L1gAIu(53sy1i`0Vqi~E^zGeXL06$>gk;8G_&*{fU z39o%r;nW^1#eWimX zb$M1Z%qMzOxM;E;ij;_B5PH(%X>o9-f`#Yj%j*O$(g1;&9jgRLrk|OxWg4c>3 zUH-2{&jS}YSkf+r_(A09EpBx6<4-*2Ch{LHbTD#4@DA8$cYq(JUx1-&4u9gg72q8u zY$anEZ)aTHY@BAYp6A&BJl+7@Zp~1_#WC<(MF01L9V|)D zPSSP1;Jf=eI8N&Tx}IfRg{`0aV&ESFr~YQ#lf&ZL{+|o}u-IAm!(a?OXBcm1#7V!J zCYiU!MvwIGZDxn=z-c^QHPFG5Q$>CdA|0MSd{jI&p+f z6#0=-uW7=%R`9FFIvB|iyfB8I6(XB(MO5P{(Hgp)u_rv}QUnO{o;ElZ% zuGbZp0;m4}e6#*PK;-L2DS3Vd7P^KB{-xM+95A}32>#B64vyc#pYUglOTPKusMy&N3Z^Y0n0f2hLgnR2??wNdT3 zdc1?<+Hdp*PUWnBJcn^zo}nVI-yhYFx%mFC;1^%*V1%D(Lujtx$2%$fa^~VWGQoRy zj>eZWEWL=^C%r_!GcYu`xwD@k8m(DUhp>P0Ms9-2~iy4=Qg;W5i^4sspQE0p(Yeml*(SMDk zxkvE0R0kuI1bKe}GYUnTP22|jLu!aahY z5xnMFg)bGnV|!))Ha!%s*A?`R7OL;YX6-eQc)kele$U>eF`9pJ+yia&93;xS+h3kCx0;l@Y zuba@-k3aD}GLhdV`Tkb$&jcSf$H7Q%!A-&Kmnr-c!Rfm>9VKifDakG4eHh2SPufe5 z(~*KdG(hS9lPJ3)hMu`1e^$zWyT}*BkY6eC>%?#9@ksZnTPpt(B0o#~-W<`tOK|-@ zPwkgp7rdv`tCPsTFZf>R&z%MTM)1$Xe-0PCQSg6>oo5T)28JSkQXu|kp5UDY*Y6E| zRPesQd0cPKVdS9T14N!)YEG9f&v2ISW^CJ(!?=?_@z}1&Un%pfw%b)KkMlzrNBYLz zeBd-Lw(U@QM2)e4_2^iHmWcjOoB5g5G2}PLz<)1#x=O$8E?K-H_#zp1BLqJrxPG5& z*#8LrdT$3yYJdBk;BCZiLq!ig>`v{n_EIH3Q}7NQWZXTLqmVd7E(K2V^d@+^2Jk12 zmqni5?@t%h@-<3u$9*{*cZi-$(Noyf!8pCsg05=?r&rq3bsK+TA0fD7o`aF61z#!n zD3RCwp-S){rN0dm`Av*V#6q4D`4Mv+jBXKLZ4CK(;M70qz4dgp=1;6wMGw8OpDx{w z2^gegx4(&B)qW{O@U-bl{&G%*_tgMz$v^iI`9T*b`4W*IE%=As6h2)-`jy$ zWL@;W;KQ#~_z47t->ref1%m76P6tYb?Skv~RL>V}gBd^f`GMh# zM`g*8X`)9z->Tbjp5XT_bg-Nrk49d(&+GFS6b#8Tva@GQzB)T=`rLWh*?7BRxqA`b z#ON;1_7!L6;l<`|ddu!PPG> zgICLDFBp!O%`P#D-Nh(ibP)=CZjUD#Vx6kTpu*XnqTIafJg=VzD0HQdRQXI?;wtjc zv))vS(W>Z6BViX6Tbnk07{7ycy80;ukEhUB;w{6I>Cl$$%_}b|^DQke^0{YUnKw5r zyO3XF3!U7hOUqbinV-!Bx3plSx6JP?%rgpHi{07shFQEwmwN6f{6GQTr#m~($n%$% z!;NJ7ii+Lxe%{%or5?^PzjQK21WfBL&*S&V`r#uM5i3mp1Wl@OycS zv(YZ3HDa{%(MUU5-UeI_!Qrb#buFlP?suzqgfmcQTHNa=ehC< z-T4I`*CH>yG`CqtpjI!=&nC}@p5#Z-OY$Qv+x|KNsQ0tJhuUbp8?E{BrKmqtuT^6hp-*)E-)Bq@|C+l#rk8M|aECHAkxu zXB4VF%kP6;r|RRgr!FbXGzzHUqAM@`mpdYcbWwBmg0ak+hxRF=HXEZ~+{`5yQS2&T z%-yi86pnXxdRinRuOx1k9m+=Sr&|uco}pSVoqtpV-3+g2_TVkjm~NUi6E!i9qVO+v zaI>egw^KjFK>({)jvzhVRpRoLF1nV+P9b})yuxx$z9jq_==`EQACip?znfZ_)|H<> zNllVdBr#51|ma-x|EkqIE?I3nwRGWs?Nn_<*o@E7dYsg~$7^ipyT62rrFALB)y z7z4@>W4TS$>$vsoR7ibj3{98ercZObVUJ=LoJNuAD5E?@KAHVSczs3XoTdQ7pMKJZ zJ7GExOttEPGsvTEJQ}s1iJzFlAHq!#sqHSW>3uOqxipae4eSt%~z!Z;Y114+7=6X>GzP zhQs%jgYvR`k`LDv3C+Lke-HLJHl*4Yk5^^Wmu9mP*&4a&YBbvaCP{zS1qahI`BKQ%BTu(5mF)#I9*@)3WX% z#j3~Af{#iXUdoVZ!A)1jlNZEOrA8Kc3-LWR)rM+?GK$+%Im0v>M{3HG{Klxo&~)!C zwd%@uQ%9OZP1RJcG^Fqr6-PP;+W{bcsfjgG zIWR#hXF|1!%u9tHZ35 zi}J4@&>W6ofXRoJH`!QamXv10ExPE(SfVSUElM>BPT&7&>wJ3C27)M_PZVJz zNOFscdZ<+Ol17Shv5+xg6=G;jNci^sy*GopI8E(Vq+$ zBc*SIGCW2q*5_<$w?WLI84#CZ6pdG|)nb!wffLjm{?^;Wz}iC5%7dqN)y~^Z2OgYJ zH%uNcQny8=>znn?_E!=R8&Eul61;q{>O@A!JhLQc-;IU2ezYk$LCV-B>9gH9A%T`U z%8lw4nanIMGXeSrNt-&FUm!^l%{XMf=(2tZXeW%{X^hMjr&e>*G;UT&9N)qfjPr;v zTx=nR!ETk9LIi^fH+}rnfjG6jj&n6=V`++%iL8x1%@ayP{Q_|x`a2}1tWZHcWM2L4|U~;ec#02-f^f(^NeGDjiXhx zdl{RV)`8QVfT&}=yB^6Jksx=e#vkZvf2PB~H{W#zq8(v5-B{Ce_44^yA#~Sm;HGJJ zsP?1#``ObIUoKb0^;j>Yp-7&IYSfv+CuIC_0KngfAn1X~(J$_v1%6#j<_EsRcCtG^gHP2gef{m*fVomfd@MoMUj1{B*Tk Yu6gn4TC)9hi`3RGDlgCYhJgLmKRqj>wg3PC literal 63176 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 diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index d43ede1..dbc02a4 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -174,7 +174,7 @@ void speol(void) { spb(13); spb(10); } -#if (defined(ARDUINO_BUILD) && (ARDUINO_VERSION >= 12)) || defined(AVROPENDOUS_BUILD) || defined(UNIX_BUILD) +#if (defined(ARDUINO) && (ARDUINO >= 12)) || defined(AVROPENDOUS_BUILD) || defined(UNIX_BUILD) // From Arduino 0011/wiring_serial.c // These apparently were removed from wiring_serial.c in 0012 diff --git a/src/bitlash.h b/src/bitlash.h index 278836e..a709f9b 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -36,16 +36,23 @@ #ifndef _BITLASH_H #define _BITLASH_H -#if defined(HIGH) || defined(ARDUINO) // this detects the Arduino build environment -#if defined(ARDUINO) && ARDUINO >= 100 +// Uncomment this to set Arduino version if < 18: +//#define ARDUINO 15 + +#if !defined(ARDUINO) && !defined(UNIX_BUILD) +#error "Building is only supported through Arduino and src/Makefile. If you have an Arduino version older than 018 which does not define the ARDUINO variable, manually set your Arduino version in src/bitlash.h" +#endif + +#if defined(ARDUINO) +#if ARDUINO < 100 + #include "WProgram.h" + #include "WConstants.h" +#else #include "Arduino.h" #define prog_char char PROGMEM #define prog_uchar char PROGMEM -#else - #include "WProgram.h" - #include "WConstants.h" #endif -#endif // HIGH || ARDUINO +#endif // defined(ARDUINO) #if !defined(UNIX_BUILD) #if defined(__SAM3X8E__) @@ -90,21 +97,15 @@ // //////////////////////////////////////////////////// // -#if defined(HIGH) || defined(ARDUINO) // this detects the Arduino build environment - -#define ARDUINO_BUILD 1 - -//#define ARDUINO_VERSION 14 // working -//#define ARDUINO_VERSION 15 // working -#define ARDUINO_VERSION 16 // working, released +#if defined(ARDUINO) // this detects the Arduino build environment // the serial support, she is changing all the time -#if ARDUINO_VERSION >= 15 +#if ARDUINO >= 15 #define beginSerial Serial.begin #define serialAvailable Serial.available #define serialRead Serial.read -#if defined(ARDUINO) && ARDUINO >= 100 +#if ARDUINO >= 100 #define serialWrite Serial.write #else #define serialWrite Serial.print @@ -112,9 +113,6 @@ #endif -// Arduino version: 11 - enable by hand if needed; see bitlash-serial.h -//#define ARDUINO_VERSION 11 - // Enable Software Serial tx support for Arduino // this enables "setbaud(4, 4800); print #4:..." // at a cost of about 400 bytes (for tx only) @@ -127,7 +125,7 @@ #else #define HIGH 1 #define LOW 0 -#endif // HIGH: arduino build +#endif // defined(ARDUINO) /////////////////////////////////////////////////////// @@ -357,7 +355,7 @@ unsigned long millis(void); // numvar is 32 bits on Arduino and 16 bits elsewhere -#if (defined(ARDUINO_BUILD) || defined(UNIX_BUILD)) && !defined(TINY_BUILD) +#if (defined(ARDUINO) || defined(UNIX_BUILD)) && !defined(TINY_BUILD) typedef long int numvar; typedef unsigned long int unumvar; #else @@ -518,7 +516,7 @@ void resetOutputHandler(void); extern serialOutputFunc serial_override_handler; #endif -#ifdef ARDUINO_BUILD +#ifdef ARDUINO void chkbreak(void); void cmd_print(void); #endif From fd3cd7f8137b23574608a09f18e65ccc355fa965 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 17:26:54 +0100 Subject: [PATCH 20/29] Use Stream and Print classes for input and output Instead of keeping pin numbers and output handler functions and deciding on the fly where to send any printed bytes, now a Print* is kept, greatly simplifying sbp() and friends. Additionally, output can now also be redirected to an arbitrary Print object by calling setOutputHandler. Similarly, for the input a Stream* is kept. This allows users of the library to select any of the available serial port or any other Stream object to use as the main console. This allows for example to use an Ethernet client, without needing the bitlash library to understand every particular ethernet library available (as long as it implements the Stream interface). This change breaks compatibility with Arduino versions older than 012, since those do not have the Print class defined, making it non-trivial to support those. This also temporarily breaks compatibility with Arduino versions below 019, which don't contain the Stream class, but this will be fixed in a subsequent commit. --- bitlash.h | 2 + src/bitlash-api.cpp | 16 ++-- src/bitlash-cmdline.cpp | 4 +- src/bitlash-functions.cpp | 8 +- src/bitlash-serial.cpp | 152 +++++++++++++++++++++++--------------- src/bitlash.h | 90 +++++++--------------- 6 files changed, 136 insertions(+), 136 deletions(-) diff --git a/bitlash.h b/bitlash.h index ac853af..fad38ec 100644 --- a/bitlash.h +++ b/bitlash.h @@ -51,6 +51,7 @@ // Start Bitlash, and give it cycles to do stuff // void initBitlash(unsigned long baud); // start up and set baud rate +void initBitlash(Stream& stream); void runBitlash(void); // call this in loop(), frequently // Bitlash variables are of type "numvar" @@ -98,6 +99,7 @@ numvar getstringarg(numvar which); typedef void (*serialOutputFunc)(byte); byte serialIsOverridden(void); void setOutputHandler(serialOutputFunc); +void setOutputHandler(Print& newHandler); void setOutput(byte pin); void resetOutputHandler(void); numvar func_printf_handler(byte, byte); diff --git a/src/bitlash-api.cpp b/src/bitlash-api.cpp index 0d4be6f..d615c36 100644 --- a/src/bitlash-api.cpp +++ b/src/bitlash-api.cpp @@ -50,13 +50,8 @@ numvar doCommand(const char *cmd) { } -void initBitlash(unsigned long baud) { - -#if defined(TINY_BUILD) - beginSerial(9600); -#else - beginSerial(baud); -#endif +void initBitlash(Stream& stream) { + blout = bloutdefault = blconsole = &stream; #if defined(ARM_BUILD) eeinit(); @@ -76,3 +71,10 @@ void initBitlash(unsigned long baud) { initlbuf(); } +void initBitlash(unsigned long baud) { + #if defined(TINY_BUILD) + baud = 9600; + #endif + DEFAULT_CONSOLE.begin(baud); + initBitlash(DEFAULT_CONSOLE); +} diff --git a/src/bitlash-cmdline.cpp b/src/bitlash-cmdline.cpp index 6c5a8fc..4aae487 100644 --- a/src/bitlash-cmdline.cpp +++ b/src/bitlash-cmdline.cpp @@ -106,7 +106,7 @@ void initlbuf(void) { prompt(); // flush any pending serial input - while (serialAvailable()) serialRead(); + while (blconsole->read() >= 0) /* nothing */; } @@ -197,7 +197,7 @@ void doCharacter(char c) { void runBitlash(void) { // Pipe the serial input into the command handler - if (serialAvailable()) doCharacter(serialRead()); + if (blconsole->available()) doCharacter(blconsole->read()); // Background macro handler: feed it one call each time through runBackgroundTasks(); diff --git a/src/bitlash-functions.cpp b/src/bitlash-functions.cpp index df0f57e..80348ec 100644 --- a/src/bitlash-functions.cpp +++ b/src/bitlash-functions.cpp @@ -190,16 +190,16 @@ numvar func_bitwrite(void) { reqargs(3); return arg3 ? func_bitset() : func_bitc numvar func_getkey(void) { if (getarg(0) > 0) sp((const char *) getarg(1)); - while (!serialAvailable()) {;} // blocking! - return (numvar) serialRead(); + while (!blconsole->available()) {;} // blocking! + return (numvar) blconsole->read(); } numvar func_getnum(void) { numvar num = 0; if (getarg(0) > 0) sp((const char *) getarg(1)); for (;;) { - while (!serialAvailable()) {;} // blocking! - int k = serialRead(); + while (!blconsole->available()) {;} // blocking! + int k = blconsole->read(); if ((k == '\r') || (k == '\n')) { speol(); return num; diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index dbc02a4..82d8c1a 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -35,11 +35,9 @@ ***/ #include "bitlash.h" -// The default default outpin is, of course, zero -#ifndef DEFAULT_OUTPIN -#define DEFAULT_OUTPIN 0 -#endif -byte outpin = DEFAULT_OUTPIN; // output pin +Stream *blconsole = &DEFAULT_CONSOLE; +Print *bloutdefault = blconsole; +Print *blout = blconsole; #ifdef SOFTWARE_SERIAL_TX @@ -48,10 +46,46 @@ byte outpin = DEFAULT_OUTPIN; // output pin #ifndef NUMPINS #define NUMPINS 32 // default to Arduino Diecimila/168..328 #endif -int bittime[NUMPINS]; // bit times (1000000/baud) per pin, 0 = uninitialized // set output back to 'stdout' ;) -void resetOutput(void) { outpin = DEFAULT_OUTPIN; } +void resetOutput(void) { blout = bloutdefault; } + +// TX-only minimal software serial implementation +class SoftwareSerialTX : public Print { +public: + uint8_t pin; + static uint16_t bittime[NUMPINS]; // bit times (1000000/baud) per pin, 0 = uninitialized + + // bit whack a byte out the port designated by 'outpin' +#if defined(ARDUINO) && ARDUINO < 100 + virtual void write(uint8_t c) { +#else + virtual size_t write(uint8_t c) { +#endif + const uint16_t bt = bittime[this->pin]; + char bits = 8; // 8 data bits + digitalWrite(this->pin, LOW); + delayMicroseconds(bt); + while (bits--) { + //if ((c & 1) == 0) digitalWrite(outpin, LOW); + //else digitalWrite(outpin, HIGH); + digitalWrite(this->pin, c & 1); + delayMicroseconds(bt); + c >>= 1; + } + digitalWrite(this->pin, HIGH); + delayMicroseconds(bt<<1); +#if !(defined(ARDUINO) && ARDUINO < 100) + return 1; +#endif + } + + +}; + +uint16_t SoftwareSerialTX::bittime[]; + +static SoftwareSerialTX sstx; void chkpin(char pin) { // TODO: fix this warning re: comparison @@ -61,12 +95,12 @@ void chkpin(char pin) { numvar setBaud(numvar pin, unumvar baud) { chkpin(pin); -//#ifndef SOFTWARE_SERIAL_TX +#ifdef DEFAULT_OUTPIN if (pin == DEFAULT_OUTPIN) { - beginSerial(baud); + DEFAULT_CONSOLE.begin(baud); return 0; } -//#endif +#endif #ifdef ALTERNATE_OUTPIN else if (pin == ALTERNATE_OUTPIN) { @@ -75,45 +109,36 @@ numvar setBaud(numvar pin, unumvar baud) { } #endif - bittime[pin] = (1000000/baud) - clockCyclesToMicroseconds(50); + sstx.bittime[pin] = (1000000/baud) - clockCyclesToMicroseconds(50); pinMode(pin, OUTPUT); // make it an output digitalWrite(pin, HIGH); // set idle - delayMicroseconds(bittime[pin]); // let it quiesce - return bittime[pin]; + delayMicroseconds(sstx.bittime[pin]); // let it quiesce + return sstx.bittime[pin]; } void setOutput(byte pin) { chkpin(pin); - outpin = pin; -#ifdef HARDWARE_SERIAL_TX - // skip soft baud check for the hardware uart - if (outpin != DEFAULT_OUTPIN) +#ifdef DEFAULT_OUTPIN + if (pin == DEFAULT_OUTPIN) { + blout = &DEFAULT_CONSOLE; + return; + } #endif + #ifdef ALTERNATE_OUTPIN - if (outpin != ALTERNATE_OUTPIN) + if (pin == ALTERNATE_OUTPIN) { + blout = &Serial1; + return; + } #endif // set the softserial baud if it's not already set - if (!bittime[outpin]) setBaud(pin, DEFAULT_SECONDARY_BAUD); + if (!sstx.bittime[pin]) setBaud(pin, DEFAULT_SECONDARY_BAUD); + sstx.pin = pin; + blout = &sstx; } -// bit whack a byte out the port designated by 'outpin' -void whackabyte(unsigned char c) { - int bt = bittime[outpin]; - char bits = 8; // 8 data bits - digitalWrite(outpin, LOW); - delayMicroseconds(bt); - while (bits--) { - //if ((c & 1) == 0) digitalWrite(outpin, LOW); - //else digitalWrite(outpin, HIGH); - digitalWrite(outpin, c & 1); - delayMicroseconds(bt); - c >>= 1; - } - digitalWrite(outpin, HIGH); - delayMicroseconds(bt<<1); -} #endif // SOFTWARE_SERIAL_TX @@ -125,16 +150,40 @@ void whackabyte(unsigned char c) { // serialOutputFunc serial_override_handler; +class PrintToFunction : public Print { +public: + serialOutputFunc func; + +#if defined(ARDUINO) && ARDUINO < 100 + virtual void write(uint8_t c) +#else + virtual size_t write(uint8_t c) +#endif + { + func (c); +#if !(defined(ARDUINO) && ARDUINO < 100) + return 1; +#endif + } +}; + +static PrintToFunction outputHandlerPrint; + byte serialIsOverridden(void) { - return serial_override_handler != 0; + return bloutdefault != blconsole; } void setOutputHandler(serialOutputFunc newHandler) { - serial_override_handler = newHandler; + outputHandlerPrint.func = newHandler; + blout = bloutdefault = &outputHandlerPrint; +} + +void setOutputHandler(Print& print) { + blout = bloutdefault = &print; } void resetOutputHandler(void) { - serial_override_handler = 0; + blout = bloutdefault = blconsole; } #endif @@ -146,31 +195,12 @@ void resetOutputHandler(void) { // // this is a pinchpoint on output. all output funnels through spb. // -#if defined(HARDWARE_SERIAL_TX) || defined(SOFTWARE_SERIAL_TX) void spb(char c) { -#ifdef HARDWARE_SERIAL_TX - if (outpin == DEFAULT_OUTPIN) { - -#ifdef SERIAL_OVERRIDE - if (serial_override_handler) (*serial_override_handler)(c); - else -#endif - serialWrite(c); - return; - } -#endif -#ifdef ALTERNATE_OUTPIN - if (outpin == ALTERNATE_OUTPIN) { Serial1.print(c); return; } -#endif -#ifdef SOFTWARE_SERIAL_TX - whackabyte(c); -#endif + blout->write((uint8_t)c); } + void sp(const char *str) { while (*str) spb(*str++); } void speol(void) { spb(13); spb(10); } -#else -// handle no-serial case -#endif @@ -233,8 +263,8 @@ void chkbreak(void) { // check serial input stream for ^C break void chkbreak(void) { - if (serialAvailable()) { // allow ^C to break out - if (serialRead() == 3) { // BUG: this gobblesnarfs input characters! - need serialPeek() + if (blconsole->available()) { // allow ^C to break out + if (blconsole->read() == 3) { // BUG: this gobblesnarfs input characters! - need serialPeek() msgpl(M_ctrlc); longjmp(env, X_EXIT); } diff --git a/src/bitlash.h b/src/bitlash.h index a709f9b..a88733b 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -99,26 +99,23 @@ // #if defined(ARDUINO) // this detects the Arduino build environment -// the serial support, she is changing all the time -#if ARDUINO >= 15 -#define beginSerial Serial.begin -#define serialAvailable Serial.available -#define serialRead Serial.read - -#if ARDUINO >= 100 - #define serialWrite Serial.write +#ifdef SERIAL_PORT_MONITOR +#define DEFAULT_CONSOLE SERIAL_PORT_MONITOR #else - #define serialWrite Serial.print +// Support 1.0.5 and below and 1.5.4 and below, that don't have +// SERIAL_PORT_MONITOR defined +#define DEFAULT_CONSOLE Serial #endif -#endif +// Assume DEFAULT_CONSOLE lives at pin 0 (Arduino headers don't have +// any way of finding out). Might be undef'd or redefined below. +#define DEFAULT_OUTPIN 0 // Enable Software Serial tx support for Arduino // this enables "setbaud(4, 4800); print #4:..." // at a cost of about 400 bytes (for tx only) // #define SOFTWARE_SERIAL_TX 1 -#define HARDWARE_SERIAL_TX 1 #define MINIMUM_FREE_RAM 50 @@ -140,18 +137,6 @@ #if defined(__AVR_ATmega644P__) #define SANGUINO -//void beginSerial(unsigned long baud) { Serial.begin(baud); } -//char serialAvailable(void) { return Serial.available(); } -//char serialRead(void) { return Serial.read(); } -//void serialWrite(char c) { return Serial.print(c); } - -#ifndef beginSerial -#define beginSerial Serial.begin -#define serialAvailable Serial.available -#define serialRead Serial.read -#define serialWrite Serial.print -#endif - // Sanguino has 24 digital and 8 analog io pins #define NUMPINS (24+8) @@ -159,6 +144,7 @@ // Sanguino alternate hardware serial port tx output is on pin 11 (rx on 10) #define SANGUINO_DEFAULT_SERIAL 9 #define SANGUINO_ALTERNATE_SERIAL 11 +#undef DEFAULT_OUTPIN #define DEFAULT_OUTPIN SANGUINO_DEFAULT_SERIAL #define ALTERNATE_OUTPIN SANGUINO_ALTERNATE_SERIAL @@ -178,13 +164,6 @@ // #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define MEGA 1 -#endif - -#if defined(MEGA) -#define beginSerial Serial.begin -#define serialAvailable Serial.available -#define serialRead Serial.read -#define serialWrite Serial.print // MEGA has 54 digital and 16 analog pins #define NUMPINS (54+16) @@ -195,6 +174,7 @@ // #define MEGA_DEFAULT_SERIAL 1 #define MEGA_ALTERNATE_SERIAL 18 +#undef DEFAULT_OUTPIN #define DEFAULT_OUTPIN MEGA_DEFAULT_SERIAL #define ALTERNATE_OUTPIN MEGA_ALTERNATE_SERIAL @@ -202,11 +182,6 @@ #if defined(__AVR_ATmega64__) -#define beginSerial Serial1.begin -#define serialAvailable Serial1.available -#define serialRead Serial1.read -#define serialWrite Serial1.print - #define NUMPINS (53) #endif @@ -221,12 +196,7 @@ #undef MINIMUM_FREE_RAM #define MINIMUM_FREE_RAM 20 #define NUMPINS 6 -//#undef HARDWARE_SERIAL_TX #undef SOFTWARE_SERIAL_TX -//#define SOFTWARE_SERIAL_TX 1 - -//#include "usbdrv.h" - #endif // TINY_BUILD @@ -247,13 +217,9 @@ #if defined(AVROPENDOUS_BUILD) #define MINIMUM_FREE_RAM 20 #define NUMPINS 24 -#undef HARDWARE_SERIAL_TX #undef SOFTWARE_SERIAL_TX -void beginSerial(unsigned long baud) { ; } -#define serialAvailable usbAvailable -#define serialRead usbRead -#define serialWrite usbWrite -#include +// Serial is virtual (USB), so no corresponding pin +#undef DEFAULT_OUTPIN #endif // defined AVRO #define TEENSY @@ -273,13 +239,9 @@ void beginSerial(unsigned long baud) { ; } #if defined(AVROPENDOUS_BUILD) #define MINIMUM_FREE_RAM 50 #define NUMPINS 40 -#undef HARDWARE_SERIAL_TX #undef SOFTWARE_SERIAL_TX -void beginSerial(unsigned long baud) { ; } -#define serialAvailable usbAvailable -#define serialRead usbRead -#define serialWrite usbWrite -#include +// Serial is virtual (USB), so no corresponding pin +#undef DEFAULT_OUTPIN #endif // AVRO #define TEENSY2 @@ -306,7 +268,6 @@ void beginSerial(unsigned long baud) { ; } #ifdef UNIX_BUILD #define MINIMUM_FREE_RAM 200 #define NUMPINS 32 -#undef HARDWARE_SERIAL_TX #undef SOFTWARE_SERIAL_TX #define beginSerial(x) @@ -364,14 +325,6 @@ typedef unsigned int unumvar; #endif // arduino_build -#ifdef AVROPENDOUS_BUILD -// USB integration -uint8_t usbAvailable(void); -int usbRead(void); -void usbWrite(uint8_t); -#endif // avropendous - - // Function prototypes @@ -379,6 +332,7 @@ void usbWrite(uint8_t); // bitlash-api.c // void initBitlash(unsigned long baud); // start up and set baud rate +void initBitlash(Stream& stream); void runBitlash(void); // call this in loop(), frequently numvar doCommand(const char *); // execute a command from your sketch void doCharacter(char); // pass an input character to the line editor @@ -512,8 +466,8 @@ void resetOutput(void); typedef void (*serialOutputFunc)(byte); byte serialIsOverridden(void); void setOutputHandler(serialOutputFunc); +void setOutputHandler(Print&); void resetOutputHandler(void); -extern serialOutputFunc serial_override_handler; #endif #ifdef ARDUINO @@ -523,6 +477,18 @@ void cmd_print(void); numvar func_printf_handler(byte, byte); +// The Stream where input is read from and print writes to when there is +// not output handler set. +extern Stream *blconsole; + +// The Print object where the print command normally goes (e.g. when not +// redirected with print #10: "foo") +extern Print *bloutdefault; + +// The Print object where the print command goes right now +extern Print *blout; + + ///////////////////////////////////////////// // bitlash-taskmgr.c // From bf55c69cedcf776bbba2ab37414cae34467e4819 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 09:48:31 +0100 Subject: [PATCH 21/29] Allow removing support for arbitrary console Streams By defining DEFAULT_CONSOLE_ONLY, the initBitlash(Stream*) function is removed and the console is fixed to whatever DEFAULT_CONSOLE defines. Doing this allows the compiler to optimize away most of the overhead (like vtable lookups) involved. Arduino versions below 019 don't contain the Stream class, so for those versions DEFAULT_CONSOLE_ONLY is automatically defined to make those work again. However, since bitlash.h does not include src/bitlash.h, this does not work completely yet. Versions below 019 will still define try to define initBitlash(Stream&) in bitlash.h, breaking the build. This will be fixed by restructuring the include files in a few commits. --- src/bitlash-api.cpp | 13 +++++++++---- src/bitlash-serial.cpp | 3 +++ src/bitlash.h | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/bitlash-api.cpp b/src/bitlash-api.cpp index d615c36..bc6af8f 100644 --- a/src/bitlash-api.cpp +++ b/src/bitlash-api.cpp @@ -50,9 +50,7 @@ numvar doCommand(const char *cmd) { } -void initBitlash(Stream& stream) { - blout = bloutdefault = blconsole = &stream; - +static void initBitlashInternal() { #if defined(ARM_BUILD) eeinit(); #endif @@ -71,10 +69,17 @@ void initBitlash(Stream& stream) { initlbuf(); } +#ifndef DEFAULT_CONSOLE_ONLY +void initBitlash(Stream& stream) { + blout = bloutdefault = blconsole = &stream; + initBitlashInternal(); +} +#endif + void initBitlash(unsigned long baud) { #if defined(TINY_BUILD) baud = 9600; #endif DEFAULT_CONSOLE.begin(baud); - initBitlash(DEFAULT_CONSOLE); + initBitlashInternal(); } diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index 82d8c1a..eb925b1 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -35,7 +35,10 @@ ***/ #include "bitlash.h" +#ifndef DEFAULT_CONSOLE_ONLY Stream *blconsole = &DEFAULT_CONSOLE; +#endif + Print *bloutdefault = blconsole; Print *blout = blconsole; diff --git a/src/bitlash.h b/src/bitlash.h index a88733b..691be5b 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -89,6 +89,9 @@ // cost: ~400 bytes flash //#define PARSER_TRACE 1 +// Define this to disable the initBitlash(Stream*) function and have the +// console I/O fixed to DEFAULT_CONSOLE (saves program memory) +//#define DEFAULT_CONSOLE_ONLY //////////////////////////////////////////////////// @@ -124,6 +127,11 @@ #define LOW 0 #endif // defined(ARDUINO) +// Arduino < 019 does not have the Stream class, so don't support +// passing a different Stream object to initBitlash +#if defined(ARDUINO) && ARDUINO < 19 +#define DEFAULT_CONSOLE_ONLY +#endif /////////////////////////////////////////////////////// // @@ -332,7 +340,9 @@ typedef unsigned int unumvar; // bitlash-api.c // void initBitlash(unsigned long baud); // start up and set baud rate +#ifndef DEFAULT_CONSOLE_ONLY void initBitlash(Stream& stream); +#endif void runBitlash(void); // call this in loop(), frequently numvar doCommand(const char *); // execute a command from your sketch void doCharacter(char); // pass an input character to the line editor @@ -479,7 +489,15 @@ numvar func_printf_handler(byte, byte); // The Stream where input is read from and print writes to when there is // not output handler set. +#ifndef DEFAULT_CONSOLE_ONLY extern Stream *blconsole; +#else +// Console is fixed to DEFAULT_CONSOLE, so make blconsole a unchangeable +// pointer to DEFAULT_CONSOLE. By also copying the type of +// DEFAULT_CONSOLE, the compiler can optimize away all vtable operations +// for minimal code overhead +__typeof__(DEFAULT_CONSOLE) * const blconsole = &DEFAULT_CONSOLE; +#endif // The Print object where the print command normally goes (e.g. when not // redirected with print #10: "foo") From f13c25296c5dcdbef550eac8fd378845d64c80bd Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 30 Jan 2014 09:52:59 +0100 Subject: [PATCH 22/29] Optimize when SERIAL_OVERRIDE and/or SOFTWARE_SERIAL_TX are disabled In these cases, either or both of the blout and bloutdefault global variables are not strictly required. By cleverly making these variables reference each other, the compiler can optimize them away, without having to change the code that uses these variables. --- src/bitlash-serial.cpp | 5 +++++ src/bitlash.h | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index eb925b1..c4b5d26 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -39,8 +39,13 @@ Stream *blconsole = &DEFAULT_CONSOLE; #endif +#ifdef SERIAL_OVERRIDE Print *bloutdefault = blconsole; +#endif + +#ifdef SOFTWARE_SERIAL_TX Print *blout = blconsole; +#endif #ifdef SOFTWARE_SERIAL_TX diff --git a/src/bitlash.h b/src/bitlash.h index 691be5b..ec706a3 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -501,11 +501,28 @@ __typeof__(DEFAULT_CONSOLE) * const blconsole = &DEFAULT_CONSOLE; // The Print object where the print command normally goes (e.g. when not // redirected with print #10: "foo") +#ifdef SERIAL_OVERRIDE extern Print *bloutdefault; +#else +// SERIAL_OVERRIDE is disabled, so print redirection should always just +// reset blout to blconsole. Using this define, we essentially make both +// identifiers refer to the same variable. +#define bloutdefault blconsole +#endif // The Print object where the print command goes right now +#ifdef SOFTWARE_SERIAL_TX extern Print *blout; +#else +// SOFTWARE_SERIAL_TX is disabled, so printing should always just go to +// bloutdefault. Using this define, we essentiallyl make both +// identifiers refer to the same variable. +#define blout bloutdefault +#endif +// Note that if SOFTWARE_SERIAL_TX and SERIAL_OVERRIDE are disabled, +// then blconsole, bloutdefault and blout are all effectively the same +// variable. ///////////////////////////////////////////// // bitlash-taskmgr.c From 6e178c8adbd57dd9f65842ee84f4d2616cbe16a7 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 7 Feb 2014 16:06:12 +0100 Subject: [PATCH 23/29] Drop code for Arduino version < 012 Since a few commits, bitlash does not support these versions anymore, so this code is no longer useful. --- src/bitlash-serial.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index c4b5d26..052c297 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -211,11 +211,6 @@ void sp(const char *str) { while (*str) spb(*str++); } void speol(void) { spb(13); spb(10); } - -#if (defined(ARDUINO) && (ARDUINO >= 12)) || defined(AVROPENDOUS_BUILD) || defined(UNIX_BUILD) -// From Arduino 0011/wiring_serial.c -// These apparently were removed from wiring_serial.c in 0012 - void printIntegerInBase(unumvar n, uint8_t base, numvar width, byte pad) { char buf[8 * sizeof(numvar)]; // stack for the digits char *ptr = buf; @@ -252,9 +247,6 @@ void printInteger(numvar n, numvar width, byte pad) { } void printHex(unumvar n) { printIntegerInBase(n, 16, 0, '0'); } void printBinary(unumvar n) { printIntegerInBase(n, 2, 0, '0'); } -#endif - - #if defined(UNIX_BUILD) From 2f5c7dfd1d35fa795dc8f4726e53ab3051fafefd Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 7 Feb 2014 16:00:04 +0100 Subject: [PATCH 24/29] Don't include WConstants.h Wconstants only exists before Arduino 1.0 and includes only wiring.h, which is always included by WProgram.h already. Looking in the Arduino history, WConstants has always only included wiring.h. Furthermore, WProgram includes wiring.h since Arduino 012. Since we don't support Arduino < 012 anymore, we can drop this include without breaking anything. --- src/bitlash.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bitlash.h b/src/bitlash.h index ec706a3..e765df1 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -46,7 +46,6 @@ #if defined(ARDUINO) #if ARDUINO < 100 #include "WProgram.h" - #include "WConstants.h" #else #include "Arduino.h" #define prog_char char PROGMEM From 9f340cda00f58af49b2e1cfb8d1e7cf2a6eb49ed Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 29 Jan 2014 17:32:32 +0100 Subject: [PATCH 25/29] In chkbreak, no longer gobble an input This is possible since we now have a complete Stream object available and thus can just use the peek() method. Arduino versions below 1.0 did not have peek, so we resort to the old behaviour then. --- src/bitlash-serial.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index 052c297..cf08c50 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -263,11 +263,17 @@ void chkbreak(void) { // check serial input stream for ^C break void chkbreak(void) { - if (blconsole->available()) { // allow ^C to break out - if (blconsole->read() == 3) { // BUG: this gobblesnarfs input characters! - need serialPeek() - msgpl(M_ctrlc); - longjmp(env, X_EXIT); - } + // allow ^C to break out +#if defined(ARDUINO) && ARDUINO < 100 + // Arduino before 1.0 didn't have peek(), so just read a + // byte (this discards a byte when it wasn't ^C, though... + if (blconsole->read() == 3) { +#else + if (blconsole->peek() == 3) { + blconsole->read(); +#endif + msgpl(M_ctrlc); + longjmp(env, X_EXIT); } if (func_free() < MINIMUM_FREE_RAM) overflow(M_stack); } From 8409415f771663f904338f73f94a60783e7e5400 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 5 Feb 2014 10:35:27 +0100 Subject: [PATCH 26/29] Fix UNIX_BUILD by using the ArduinoUnix library The switch to using Stream and Print classes broke UNIX_BUILD, since no definitions of those classes were available. Instead of also adding those to bitlash, this switches to using the ArduinoUnix library and allows removing all of the unix-specific implementation of the Arduino API as well. This requires the ArduinoUnix library to be available (by default in a directory called `ArduinoUnix` besides the bitlash directory, but this can be changed by setting ARDUINO_UNIX_PATH). --- README-UNIX.md | 5 ++ src/Makefile | 8 ++- src/bitlash-unix.cpp | 155 +------------------------------------------ src/bitlash.h | 47 ++----------- 4 files changed, 16 insertions(+), 199 deletions(-) diff --git a/README-UNIX.md b/README-UNIX.md index aa21b5b..4db9711 100644 --- a/README-UNIX.md +++ b/README-UNIX.md @@ -8,6 +8,11 @@ Here are some notes on experimental Unix support for Bitlash. - the basic functions work - on OS X, numvar is 64 bits, so everything is 64 bits wide - Makefile in src/ will build the binary as src/bin/bitlash + - Requires the ArduinoUnix library, which can be cloned from + https://github.com/matthijskooijman/ArduinoUnix. The makefile + normally looks for a directory called "ArduinoUnix" next to + the bitlash directory, but this can be changed by setting + ARDUINO_UNIX_PATH when calling make. - there are some precompiled binaries in src/bin/ - eeprom is simulated diff --git a/src/Makefile b/src/Makefile index 85ebf8b..508abee 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,10 @@ -CFLAGS := -DUNIX_BUILD -pthread +ARDUINO_UNIX_PATH ?= ../../ArduinoUnix + +include $(ARDUINO_UNIX_PATH)/Makefile.mk + +CFLAGS := -DUNIX_BUILD -pthread -I$(ARDUINO_UNIX_INCLUDE_PATH) LDFLAGS := -lstdc++ -pthread -SOURCES := $(wildcard *.cpp) +SOURCES := $(wildcard *.cpp) $(ARDUINO_UNIX_SOURCES) BINARY := bin/bitlash PREFIX := /usr/local BINPATH := $(PREFIX)/bin diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index 1489793..85b47d3 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -68,159 +68,6 @@ boot segfaults ;) char bitlash_directory[PATH_LEN]; #define DEFAULT_BITLASH_PATH "/.bitlash/" - -#if _POSIX_TIMERS // not on the Mac, unfortunately -struct timespec startup_time, current_time, elapsed_time; - -// from http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/ -struct timespec time_diff(struct timespec start, struct timespec end) { - struct timespec temp; - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - return temp; -} - -void init_millis(void) { - clock_gettime(CLOCK_REALTIME, &startup_time); -} - -unsigned long millis(void) { - clock_gettime(CLOCK_REALTIME, ¤t_time); - elapsed_time = time_diff(startup_time, current_time); - return (elapsed_time.tv_sec * 1000UL) + (elapsed_time.tv_nsec / 1000000UL); -} -#else -#include - -unsigned long startup_millis, current_millis, elapsed_millis; -struct timeval startup_time, current_time; - -// after http://laclefyoshi.blogspot.com/2011/05/getting-nanoseconds-in-c-on-freebsd.html -void init_millis(void) { - gettimeofday(&startup_time, NULL); - startup_millis = (startup_time.tv_sec * 1000) + (startup_time.tv_usec /1000); -} - -unsigned long millis(void) { - gettimeofday(¤t_time, NULL); - current_millis = (current_time.tv_sec * 1000) + (current_time.tv_usec / 1000); - elapsed_millis = current_millis - startup_millis; - return elapsed_millis; -} - -#endif - - -#if 0 -// after http://stackoverflow.com/questions/4025891/create-a-function-to-check-for-key-press-in-unix-using-ncurses -//#include - -int init_keyboard(void) { - initscr(); - cbreak(); - noecho(); - nodelay(stdscr, TRUE); - scrollok(stdscr, TRUE); -} - -int serialAvailable(void) { - int ch = getch(); - - if (ch != ERR) { - ungetch(ch); - return 1; - } - else return 0; -} - -int serialRead(void) { return getch(); } -#endif - -#if 0 -//#include "conio.h" -int lookahead_key = -1; - -int serialAvailable(void) { - if (lookahead_key != -1) return 1; - lookahead_key = mygetch(); - if (lookahead_key == -1) return 0; - //printf("getch: %d ", lookahead_key); - return 1; -} - -int serialRead(void) { - if (lookahead_key != -1) { - int retval = lookahead_key; - lookahead_key = -1; - //printf("key: %d", retval); - return retval; - } - return mygetch(); -} -#endif - -#if 1 -int serialAvailable(void) { - return 0; -} - -int serialRead(void) { - return '$'; -} - -#endif - -void spb (char c) { - if (serial_override_handler) (*serial_override_handler)(c); - else { - putchar(c); - //printf("%c", c); - fflush(stdout); - } -} -void sp(const char *str) { while (*str) spb(*str++); } -void speol(void) { spb(13); spb(10); } - -numvar setBaud(numvar pin, unumvar baud) { return 0; } - -// stubs for the hardware IO functions -// -unsigned long pins; -void pinMode(byte pin, byte mode) { ; } -int digitalRead(byte pin) { return ((pins & (1< Date: Fri, 7 Feb 2014 19:05:05 +0100 Subject: [PATCH 27/29] Add vim swapfiles to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5321bb1..821dbbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.swp +*.swo */.DS_Store examples/bitlashdemo/applet examples/*/applet From b51c5b144f6d15c6a104e5095b6a0681fb737207 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 8 Feb 2014 21:13:30 +0100 Subject: [PATCH 28/29] Remove unneeded macro check in numvar declaration This line checked for defined(ARDUINO) || defined(UNIX_BUILD), but that is guaranteed to be always true by a check further up. --- src/bitlash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitlash.h b/src/bitlash.h index 50fc488..439bdfd 100644 --- a/src/bitlash.h +++ b/src/bitlash.h @@ -302,7 +302,7 @@ // numvar is 32 bits on Arduino and 16 bits elsewhere -#if (defined(ARDUINO) || defined(UNIX_BUILD)) && !defined(TINY_BUILD) +#if !defined(TINY_BUILD) typedef long int numvar; typedef unsigned long int unumvar; #else From 3ac8e2460b1ef1acce48b72042b0f3c2c0ed9eb2 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 7 Feb 2014 19:07:54 +0100 Subject: [PATCH 29/29] Restructure the header files The main goal of this commit is make the build options available to the public API, since not all functions are available with all options. This was previously not a problem for most functions (they would be declared but not defined, which is ok if they're not used either). However, on Arduino versions < 019, the Stream class is not available, so declaring initBitlash(Stream&) would break the build, even when it was not used. Fixing this is the original reason for this commit. This commit mostly moves declarations around, it should not make any functional changes. In addition to moving declarations between files, it also reorganizes the ordering of them and makes comments more consistent. The major changes in this commit are: - The public API used to be in bitlash.h, but is now moved to src/bitlash-public.h. bitlash.h still exists for sketches to include, but it just includes src/bitlash-public.h. - The private API and build config used to be in src/bitlash.h, but is now split into src/bitlash-private.h for the private API and src/bitlash-config.h for all build config related macros. src/bitlash.h no longer exists. - src/bitlash-public.h now includes src/bitlash-config.h, to allow the public API to be different depending on the build config. - A number of functions in the public API are now conditionally declared based on the build config. This matches the public API declarations to the actual function definitions in the .cpp files. - src/bitlash-private.h now includes src/bitlash-public.h. This allows removing duplicate declarations for the public API functions and types. - In the public API, the type of numvar now properly depends on TINY_BUILD. Before, the public API would always declare it as long, whereas the implementation would declare it as int for TINY_BUILD. This will probably have caused TINY_BUILD to be broken. --- bitlash.h | 74 +----- src/bin/bitlash | Bin 54029 -> 94618 bytes src/bitlash-api.cpp | 2 +- src/bitlash-builtins.cpp | 2 +- src/bitlash-cmdline.cpp | 2 +- src/bitlash-config.h | 334 +++++++++++++++++++++++++ src/bitlash-eeprom.cpp | 2 +- src/bitlash-error.cpp | 2 +- src/bitlash-functions.cpp | 2 +- src/bitlash-instream.cpp | 2 +- src/bitlash-interpreter.cpp | 2 +- src/bitlash-parser.cpp | 2 +- src/{bitlash.h => bitlash-private.h} | 351 +-------------------------- src/bitlash-public.h | 127 ++++++++++ src/bitlash-serial.cpp | 2 +- src/bitlash-taskmgr.cpp | 2 +- src/bitlash-unix-file.cpp | 2 +- src/bitlash-unix.cpp | 2 +- src/eeprom.cpp | 2 +- 19 files changed, 485 insertions(+), 429 deletions(-) create mode 100644 src/bitlash-config.h rename src/{bitlash.h => bitlash-private.h} (54%) create mode 100644 src/bitlash-public.h diff --git a/bitlash.h b/bitlash.h index fad38ec..0623a4f 100644 --- a/bitlash.h +++ b/bitlash.h @@ -33,80 +33,10 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" - #define prog_char char PROGMEM - #define prog_uchar unsigned char PROGMEM -#else - #include "WProgram.h" -#endif +#include "src/bitlash-public.h" // Un-comment the line below to expose all the internals // of the Bitlash core to your sketch. // -//#include "src/bitlash.h" - -/////////////////////// -// Start Bitlash, and give it cycles to do stuff -// -void initBitlash(unsigned long baud); // start up and set baud rate -void initBitlash(Stream& stream); -void runBitlash(void); // call this in loop(), frequently - -// Bitlash variables are of type "numvar" -// -typedef long int numvar; // bitlash returns things of type numvar -typedef unsigned long int unumvar; // sometimes unsigned interpretation is best (like millis) - - -/////////////////////// -// Pass a command to Bitlash for interpretation -// -numvar doCommand(const char *); // execute a command from your sketch -void doCharacter(char); // pass an input character to the line editor - -/////////////////////// -// Access to Numeric Variables -// -// NOTE: access to variables a..z is via an index 0..25, not the variable names. Got it? -// -numvar getVar(unsigned char); // return value of bitlash variable. id is [0..25] for [a..z] -void assignVar(unsigned char, numvar); // assign value to variable. id is [0..25] for [a..z] -numvar incVar(unsigned char); // increment variable. id is [0..25] for [a..z] - - -/////////////////////// -// Access to the Bitlash symbol table -// -// Lookup id and return TRUE if it exists -// -byte findscript(const char *); // returns TRUE if a script exists with this ID -int getValue(const char *key); // return location of macro value in EEPROM or -1 - -/////////////////////// -// Add a user function to Bitlash -// -typedef numvar (*bitlash_function)(void); -void addBitlashFunction(const char *, bitlash_function); -numvar getarg(numvar); -numvar isstringarg(numvar); -numvar getstringarg(numvar which); - -/////////////////////// -// Serial Output Capture -// -typedef void (*serialOutputFunc)(byte); -byte serialIsOverridden(void); -void setOutputHandler(serialOutputFunc); -void setOutputHandler(Print& newHandler); -void setOutput(byte pin); -void resetOutputHandler(void); -numvar func_printf_handler(byte, byte); - -/////////////////////// -// File functions -// -numvar sdcat(void); -numvar sdwrite(const char *filename, const char *contents, byte append); -numvar func_fprintf(void); +//#include "src/bitlash-private.h" diff --git a/src/bin/bitlash b/src/bin/bitlash index 8446972c660d6722091bd28fbac435561085f1d1..6c71cd5bbe7e59d2bdb73827c5e742382ee11cf9 100755 GIT binary patch literal 94618 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 }L;P!8-%lgnM10ZtA%)B%-U|FE*z?)1Yy39i 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 literal 54029 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

$li3k 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℘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 Yu6gn4TC)9hi`3RGDlgCYhJgLmKRqj>wg3PC diff --git a/src/bitlash-api.cpp b/src/bitlash-api.cpp index bc6af8f..096a059 100644 --- a/src/bitlash-api.cpp +++ b/src/bitlash-api.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" // Exception handling state diff --git a/src/bitlash-builtins.cpp b/src/bitlash-builtins.cpp index dc80669..c88a8c6 100644 --- a/src/bitlash-builtins.cpp +++ b/src/bitlash-builtins.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" /********** diff --git a/src/bitlash-cmdline.cpp b/src/bitlash-cmdline.cpp index 4aae487..de9cfef 100644 --- a/src/bitlash-cmdline.cpp +++ b/src/bitlash-cmdline.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" // Serial command line buffer diff --git a/src/bitlash-config.h b/src/bitlash-config.h new file mode 100644 index 0000000..57b5286 --- /dev/null +++ b/src/bitlash-config.h @@ -0,0 +1,334 @@ +/*** + bitlash-config.h - Build options + + Bitlash is a tiny language interpreter that provides a serial port shell environment + for bit banging and hardware hacking. + + See the file README for documentation. + + Bitlash lives at: http://bitlash.net + The author can be reached at: bill@bitlash.net + + Copyright (C) 2008-2012 Bill Roy + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. +***/ + +#ifndef _BITLASH_CONFIG_H +#define _BITLASH_CONFIG_H + +// Uncomment this to set Arduino version if < 18: +//#define ARDUINO 15 + +//////////////////////////////////////////////////// +// GLOBAL BUILD OPTIONS +//////////////////////////////////////////////////// +// +// Enable LONG_ALIASES to make the parser recognize analogRead(x) as well as ar(x), and so on +// cost: ~200 bytes flash +//#define LONG_ALIASES 1 + +// +// Enable PARSER_TRACE to make ^T toggle a parser trace debug print stream +// cost: ~400 bytes flash +//#define PARSER_TRACE 1 + +// Define this to disable the initBitlash(Stream*) function and have the +// console I/O fixed to DEFAULT_CONSOLE (saves program memory) +//#define DEFAULT_CONSOLE_ONLY + +// Enable SD card script-in-file support +//#define SDFILE + + +#if !defined(ARDUINO) && !defined(UNIX_BUILD) +#error "Building is only supported through Arduino and src/Makefile. If you have an Arduino version older than 018 which does not define the ARDUINO variable, manually set your Arduino version in src/bitlash-config.h" +#endif + +#if defined(ARDUINO) && ARDUINO < 100 + #include "WProgram.h" +#else + #include "Arduino.h" + #define prog_char char PROGMEM + #define prog_uchar char PROGMEM +#endif + +/////////////////////////////////////////////////////// +// +// Find build type +#if !defined(UNIX_BUILD) +#if defined(__SAM3X8E__) +#define ARM_BUILD 1 +#elif (defined(__MK20DX128__) || defined(__MK20DX256__)) && defined (CORE_TEENSY) + // Teensy 3 + #define ARM_BUILD 2 +#elif defined(PART_LM4F120H5QR) //support Energia.nu - Stellaris Launchpad / Tiva C Series +#define ARM_BUILD 4 //support Energia.nu - Stellaris Launchpad / Tiva C Series +#else +#define AVR_BUILD 1 +#endif +#endif // !defined(UNIX_BUILD) + +/////////////////////////////////////////////////////// +// +// UNIX BUILD +// +// See README-UNIX.md for info about how to compile +// +#ifdef UNIX_BUILD +#define MINIMUM_FREE_RAM 200 +#define NUMPINS 32 +#undef SOFTWARE_SERIAL_TX +#define E2END 2047 + +#define DEFAULT_CONSOLE StdioStream +// No corresponding pin +#undef DEFAULT_OUTPIN + +#endif // defined unix_build + +//////////////////////////////////////////////////// +// +// ARDUINO BUILD +// (This includes third-party boards like sanguino) +// +//////////////////////////////////////////////////// +// +#if defined(ARDUINO) // this detects the Arduino build environment + +#ifdef SERIAL_PORT_MONITOR +#define DEFAULT_CONSOLE SERIAL_PORT_MONITOR +#else +// Support 1.0.5 and below and 1.5.4 and below, that don't have +// SERIAL_PORT_MONITOR defined +#define DEFAULT_CONSOLE Serial +#endif + +// Assume DEFAULT_CONSOLE lives at pin 0 (Arduino headers don't have +// any way of finding out). Might be undef'd or redefined below. +#define DEFAULT_OUTPIN 0 + +// Enable Software Serial tx support for Arduino +// this enables "setbaud(4, 4800); print #4:..." +// at a cost of about 400 bytes (for tx only) +// +#define SOFTWARE_SERIAL_TX 1 + +#define MINIMUM_FREE_RAM 50 + +// Arduino < 019 does not have the Stream class, so don't support +// passing a different Stream object to initBitlash +#if ARDUINO < 19 +#define DEFAULT_CONSOLE_ONLY +#endif + +#endif // defined(ARDUINO) + + +/////////////////////////////////////////////////////// +// +// SANGUINO BUILD +// +/////////////////////////////////////////////////////// +// +// SANGUINO is auto-enabled to build for the Sanguino '644 +// if the '644 define is present +// +#if defined(__AVR_ATmega644P__) +#define SANGUINO + +// Sanguino has 24 digital and 8 analog io pins +#define NUMPINS (24+8) + +// Sanguino primary serial tx output is on pin 9 (rx on 8) +// Sanguino alternate hardware serial port tx output is on pin 11 (rx on 10) +#define SANGUINO_DEFAULT_SERIAL 9 +#define SANGUINO_ALTERNATE_SERIAL 11 +#undef DEFAULT_OUTPIN +#define DEFAULT_OUTPIN SANGUINO_DEFAULT_SERIAL +#define ALTERNATE_OUTPIN SANGUINO_ALTERNATE_SERIAL + +#endif // defined (644) + + +/////////////////////////////////////////////////////// +// +// MEGA BUILD +// +// Note: These are speculative and untested. Feedback welcome. +// +/////////////////////////////////////////////////////// +// +// MEGA is auto-enabled to build for the Arduino Mega or Mega2560 +// if the '1280/'2560 define is present +// +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define MEGA 1 + +// MEGA has 54 digital and 16 analog pins +#define NUMPINS (54+16) + +// Mega primary serial tx output is on pin 1 (rx on 0) +// Mega alternate hardware serial port tx output is on pin 18 (rx on 19) +// TODO: Support for hardware serial uart2 and uart3 +// +#define MEGA_DEFAULT_SERIAL 1 +#define MEGA_ALTERNATE_SERIAL 18 +#undef DEFAULT_OUTPIN +#define DEFAULT_OUTPIN MEGA_DEFAULT_SERIAL +#define ALTERNATE_OUTPIN MEGA_ALTERNATE_SERIAL + +#endif // defined (1280) + + +/////////////////////////////////////////////////////// +// +// Atmega64 BUILD +#if defined(__AVR_ATmega64__) +#define NUMPINS (53) +#endif + + +/////////////////////////////////////////////////////// +// +// TINY BUILD OPTIONS +// +#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny84__) +#define TINY_BUILD 1 +#undef MINIMUM_FREE_RAM +#define MINIMUM_FREE_RAM 20 +#define NUMPINS 6 +#undef SOFTWARE_SERIAL_TX +#endif // TINY_BUILD + + +/////////////////////////////////////////////////////// +// +// AVROPENDOUS and TEENSY BUILD +// +#if defined(__AVR_AT90USB162__) + +//#define AVROPENDOUS_BUILD +#if defined(AVROPENDOUS_BUILD) +#define MINIMUM_FREE_RAM 20 +#define NUMPINS 24 +#undef SOFTWARE_SERIAL_TX +// Serial is virtual (USB), so no corresponding pin +#undef DEFAULT_OUTPIN +#endif // defined AVRO + +#define TEENSY +#ifdef TEENSY +// No TEENSY options yet +#endif // defined TEENSY + +#endif // defined '162 + + +/////////////////////////////////////////////////////// +// +// AVROPENDOUS 32U4 and TEENSY2 BUILD +// +#if defined(__AVR_ATmega32U4__) + +//#define AVROPENDOUS_BUILD +#if defined(AVROPENDOUS_BUILD) +#define MINIMUM_FREE_RAM 50 +#define NUMPINS 40 +#undef SOFTWARE_SERIAL_TX +// Serial is virtual (USB), so no corresponding pin +#undef DEFAULT_OUTPIN +#endif // AVRO + +#define TEENSY2 +#if defined(TEENSY2) +// No TEENSY2 options yet +#endif // TEENSY2 + +#endif // defined '32U4 + + +//////////////////// +// +// ARM BUILD +#if defined(ARM_BUILD) + #define prog_char char +#define prog_uchar byte +#define PROGMEM +#define pgm_read_byte(b) (*(char *)(b)) +#define pgm_read_word(b) (*(int *)(b)) +#define strncpy_P strncpy +#define strcmp_P strcmp +#define strlen_P strlen +#if ARM_BUILD==1 + #define E2END 4096 +#else + // Teensy 3 + #define E2END 2048 +#endif + +#endif + +///////////////////////////////////////////// +// External EEPROM (I2C) +// +// Uncomment to enable EEPROM via I2C +// Supports a Microchip 24xx32A EEPROM module attached to the I2C bus +// http://ww1.microchip.com/downloads/en/DeviceDoc/21713J.pdf +// Specifically, the DigiX has such a module onboard +// https://digistump.com/wiki/digix/tutorials/eeprom +//#define EEPROM_MICROCHIP_24XX32A + +#define EEPROM_ADDRESS 0x50 // default EEPROM address for DigiX boards + +//////////////////////// +// +// EEPROM database begin/end offset +// +// Use the predefined constant from the avr-gcc support file +// +#if defined(EEPROM_MICROCHIP_24XX32A) + #define ENDDB 4095 + #define ENDEEPROM 4095 +#else + #define ENDDB E2END + #define ENDEEPROM E2END +#endif + + +// Enable USER_FUNCTIONS to include the add_bitlash_function() extension mechanism +// This costs about 256 bytes +// +#if !defined(TINY_BUILD) +#define USER_FUNCTIONS +#endif + +// String value buffer size +#ifdef AVR_BUILD + #define STRVALSIZE 120 +#else + #define STRVALSIZE 512 +#endif +#define STRVALLEN (STRVALSIZE-1) +#define LBUFLEN STRVALSIZE + +#endif // _BITLASH_CONFIG_H diff --git a/src/bitlash-eeprom.cpp b/src/bitlash-eeprom.cpp index 7bb6598..a140fff 100644 --- a/src/bitlash-eeprom.cpp +++ b/src/bitlash-eeprom.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" /*** diff --git a/src/bitlash-error.cpp b/src/bitlash-error.cpp index e77e4ad..7e81f3e 100644 --- a/src/bitlash-error.cpp +++ b/src/bitlash-error.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" void fatal2(char msg1, char msg2) { diff --git a/src/bitlash-functions.cpp b/src/bitlash-functions.cpp index 80348ec..c6acd64 100644 --- a/src/bitlash-functions.cpp +++ b/src/bitlash-functions.cpp @@ -31,7 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" // syntactic sugar for func_handlers() #if 0 // 15022 bytes diff --git a/src/bitlash-instream.cpp b/src/bitlash-instream.cpp index 0d69a55..d57ffe7 100644 --- a/src/bitlash-instream.cpp +++ b/src/bitlash-instream.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" #if defined(SDFILE) || defined(UNIX_BUILD) diff --git a/src/bitlash-interpreter.cpp b/src/bitlash-interpreter.cpp index 49abcbe..74be4af 100644 --- a/src/bitlash-interpreter.cpp +++ b/src/bitlash-interpreter.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" // Turn HEX_UPLOAD on to enable the hex file EEPROM uploader diff --git a/src/bitlash-parser.cpp b/src/bitlash-parser.cpp index df3a9bf..928f2de 100644 --- a/src/bitlash-parser.cpp +++ b/src/bitlash-parser.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" #if defined(AVR_BUILD) #include "avr/eeprom.h" diff --git a/src/bitlash.h b/src/bitlash-private.h similarity index 54% rename from src/bitlash.h rename to src/bitlash-private.h index 439bdfd..094f3c6 100644 --- a/src/bitlash.h +++ b/src/bitlash-private.h @@ -1,5 +1,5 @@ /*** - bitlash.h + bitlash-private.h - Private API Bitlash is a tiny language interpreter that provides a serial port shell environment for bit banging and hardware hacking. @@ -33,37 +33,13 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#ifndef _BITLASH_H -#define _BITLASH_H - -// Uncomment this to set Arduino version if < 18: -//#define ARDUINO 15 - -#if !defined(ARDUINO) && !defined(UNIX_BUILD) -#error "Building is only supported through Arduino and src/Makefile. If you have an Arduino version older than 018 which does not define the ARDUINO variable, manually set your Arduino version in src/bitlash.h" -#endif - -#if defined(ARDUINO) && ARDUINO < 100 - #include "WProgram.h" -#else - #include "Arduino.h" - #define prog_char char PROGMEM - #define prog_uchar char PROGMEM -#endif - -#if !defined(UNIX_BUILD) -#if defined(__SAM3X8E__) -#define ARM_BUILD 1 -#elif (defined(__MK20DX128__) || defined(__MK20DX256__)) && defined (CORE_TEENSY) - // Teensy 3 - #define ARM_BUILD 2 -#elif defined(PART_LM4F120H5QR) //support Energia.nu - Stellaris Launchpad / Tiva C Series -#define ARM_BUILD 4 //support Energia.nu - Stellaris Launchpad / Tiva C Series -#else -#define AVR_BUILD 1 -#endif -#endif // !defined(UNIX_BUILD) +#ifndef _BITLASH_PRIVATE_H +#define _BITLASH_PRIVATE_H +// bitlash-public.h declares public functions and types +// bitlash-private.h declares private (internal) functions and types +// bitlash-config.h contains (sometimes tweakable) build parameters +#include "bitlash-public.h" #if defined(AVR_BUILD) #include "avr/pgmspace.h" @@ -73,258 +49,6 @@ #include #include -//////////////////////////////////////////////////// -// GLOBAL BUILD OPTIONS -//////////////////////////////////////////////////// -// -// Enable LONG_ALIASES to make the parser recognize analogRead(x) as well as ar(x), and so on -// cost: ~200 bytes flash -//#define LONG_ALIASES 1 - -// -// Enable PARSER_TRACE to make ^T toggle a parser trace debug print stream -// cost: ~400 bytes flash -//#define PARSER_TRACE 1 - -// Define this to disable the initBitlash(Stream*) function and have the -// console I/O fixed to DEFAULT_CONSOLE (saves program memory) -//#define DEFAULT_CONSOLE_ONLY - - -//////////////////////////////////////////////////// -// -// ARDUINO BUILD OPTIONS -// -//////////////////////////////////////////////////// -// -#if defined(ARDUINO) // this detects the Arduino build environment - -#ifdef SERIAL_PORT_MONITOR -#define DEFAULT_CONSOLE SERIAL_PORT_MONITOR -#else -// Support 1.0.5 and below and 1.5.4 and below, that don't have -// SERIAL_PORT_MONITOR defined -#define DEFAULT_CONSOLE Serial -#endif - -// Assume DEFAULT_CONSOLE lives at pin 0 (Arduino headers don't have -// any way of finding out). Might be undef'd or redefined below. -#define DEFAULT_OUTPIN 0 - -// Enable Software Serial tx support for Arduino -// this enables "setbaud(4, 4800); print #4:..." -// at a cost of about 400 bytes (for tx only) -// -#define SOFTWARE_SERIAL_TX 1 - -#define MINIMUM_FREE_RAM 50 - -#endif // defined(ARDUINO) - -// Arduino < 019 does not have the Stream class, so don't support -// passing a different Stream object to initBitlash -#if defined(ARDUINO) && ARDUINO < 19 -#define DEFAULT_CONSOLE_ONLY -#endif - -/////////////////////////////////////////////////////// -// -// SANGUINO BUILD -// -/////////////////////////////////////////////////////// -// -// SANGUINO is auto-enabled to build for the Sanguino '644 -// if the '644 define is present -// -#if defined(__AVR_ATmega644P__) -#define SANGUINO - -// Sanguino has 24 digital and 8 analog io pins -#define NUMPINS (24+8) - -// Sanguino primary serial tx output is on pin 9 (rx on 8) -// Sanguino alternate hardware serial port tx output is on pin 11 (rx on 10) -#define SANGUINO_DEFAULT_SERIAL 9 -#define SANGUINO_ALTERNATE_SERIAL 11 -#undef DEFAULT_OUTPIN -#define DEFAULT_OUTPIN SANGUINO_DEFAULT_SERIAL -#define ALTERNATE_OUTPIN SANGUINO_ALTERNATE_SERIAL - -#endif // defined (644) - - -/////////////////////////////////////////////////////// -// -// MEGA BUILD -// -// Note: These are speculative and untested. Feedback welcome. -// -/////////////////////////////////////////////////////// -// -// MEGA is auto-enabled to build for the Arduino Mega or Mega2560 -// if the '1280/'2560 define is present -// -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define MEGA 1 - -// MEGA has 54 digital and 16 analog pins -#define NUMPINS (54+16) - -// Mega primary serial tx output is on pin 1 (rx on 0) -// Mega alternate hardware serial port tx output is on pin 18 (rx on 19) -// TODO: Support for hardware serial uart2 and uart3 -// -#define MEGA_DEFAULT_SERIAL 1 -#define MEGA_ALTERNATE_SERIAL 18 -#undef DEFAULT_OUTPIN -#define DEFAULT_OUTPIN MEGA_DEFAULT_SERIAL -#define ALTERNATE_OUTPIN MEGA_ALTERNATE_SERIAL - -#endif // defined (1280) - -#if defined(__AVR_ATmega64__) - -#define NUMPINS (53) -#endif - - - -/////////////////////////////////////////////////////// -// -// TINY BUILD OPTIONS -// -#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny84__) -#define TINY_BUILD 1 -#undef MINIMUM_FREE_RAM -#define MINIMUM_FREE_RAM 20 -#define NUMPINS 6 -#undef SOFTWARE_SERIAL_TX -#endif // TINY_BUILD - - -// Enable USER_FUNCTIONS to include the add_bitlash_function() extension mechanism -// This costs about 256 bytes -// -#if !defined(TINY_BUILD) -#define USER_FUNCTIONS -#endif - -/////////////////////////////////////////////////////// -// -// AVROPENDOUS and TEENSY BUILD OPTIONS -// -#if defined(__AVR_AT90USB162__) - -//#define AVROPENDOUS_BUILD -#if defined(AVROPENDOUS_BUILD) -#define MINIMUM_FREE_RAM 20 -#define NUMPINS 24 -#undef SOFTWARE_SERIAL_TX -// Serial is virtual (USB), so no corresponding pin -#undef DEFAULT_OUTPIN -#endif // defined AVRO - -#define TEENSY -#ifdef TEENSY -#endif // defined TEENSY - -#endif // defined '162 - - -/////////////////////////////////////////////////////// -// -// ATMega32U4 BUILD OPTIONS -// -#if defined(__AVR_ATmega32U4__) - -//#define AVROPENDOUS_BUILD -#if defined(AVROPENDOUS_BUILD) -#define MINIMUM_FREE_RAM 50 -#define NUMPINS 40 -#undef SOFTWARE_SERIAL_TX -// Serial is virtual (USB), so no corresponding pin -#undef DEFAULT_OUTPIN -#endif // AVRO - -#define TEENSY2 -#if defined(TEENSY2) -#endif // TEENSY2 - -#endif // defined '32U4 - - -/////////////////////////////////////////////////////// -// -// SD CARD SUPPORT: Enable the SDFILE define for SD card script-in-file support -// -//#define SDFILE - - -/////////////////////////////////////////////////////// -// -// Unix build options -// -// See README-UNIX.md for info about how to compile -// -#ifdef UNIX_BUILD -#define MINIMUM_FREE_RAM 200 -#define NUMPINS 32 -#undef SOFTWARE_SERIAL_TX -#define E2END 2047 - -#define DEFAULT_CONSOLE StdioStream -// No corresponding pin -#undef DEFAULT_OUTPIN - -#endif // defined unix_build - - -//////////////////// -// -// ARM BUILD -#if defined(ARM_BUILD) - #define prog_char char -#define prog_uchar byte -#define PROGMEM -#define pgm_read_byte(b) (*(char *)(b)) -#define pgm_read_word(b) (*(int *)(b)) -#define strncpy_P strncpy -#define strcmp_P strcmp -#define strlen_P strlen -#if ARM_BUILD==1 - #define E2END 4096 -#else - // Teensy 3 - #define E2END 2048 -#endif - -#endif - - -// numvar is 32 bits on Arduino and 16 bits elsewhere -#if !defined(TINY_BUILD) -typedef long int numvar; -typedef unsigned long int unumvar; -#else -typedef int numvar; -typedef unsigned int unumvar; -#endif // arduino_build - - -// Function prototypes - - -///////////////////////////////////////////// -// bitlash-api.c -// -void initBitlash(unsigned long baud); // start up and set baud rate -#ifndef DEFAULT_CONSOLE_ONLY -void initBitlash(Stream& stream); -#endif -void runBitlash(void); // call this in loop(), frequently -numvar doCommand(const char *); // execute a command from your sketch -void doCharacter(char); // pass an input character to the line editor - ///////////////////////////////////////////// // bitlash-builtins.c // @@ -338,24 +62,13 @@ void initlbuf(void); void pointToError(void); void cmd_help(void); -// String value buffer size -#ifdef AVR_BUILD - #define STRVALSIZE 120 -#else - #define STRVALSIZE 512 -#endif -#define STRVALLEN (STRVALSIZE-1) -#define LBUFLEN STRVALSIZE - extern char *lbufptr; extern char lbuf[LBUFLEN]; - ///////////////////////////////////////////// // bitlash-eeprom.c // int findKey(const char *key); // return location of macro keyname in EEPROM or -1 -int getValue(const char *key); // return location of macro value in EEPROM or -1 int findoccupied(int); int findend(int); @@ -365,31 +78,6 @@ void eeputs(int); #define STARTDB 0 #define FAIL ((int)-1) -///////////////////////////////////////////// -// External EEPROM (I2C) -// -//#define EEPROM_MICROCHIP_24XX32A // Uncomment to enable EEPROM via I2C - // Supports a Microchip 24xx32A EEPROM module attached to the I2C bus - // http://ww1.microchip.com/downloads/en/DeviceDoc/21713J.pdf - // Specifically, the DigiX has such a module onboard - // https://digistump.com/wiki/digix/tutorials/eeprom - -#define EEPROM_ADDRESS 0x50 // default EEPROM address for DigiX boards - -//////////////////////// -// -// EEPROM database begin/end offset -// -// Use the predefined constant from the avr-gcc support file -// -#if defined(EEPROM_MICROCHIP_24XX32A) - #define ENDDB 4095 - #define ENDEEPROM 4095 -#else - #define ENDDB E2END - #define ENDEEPROM E2END -#endif - ///////////////////////////////////////////// // bitlash-error.c // @@ -408,10 +96,8 @@ void oops(int); // fatal exit ///////////////////////////////////////////// // bitlash-functions.c // -typedef numvar (*bitlash_function)(void); void show_user_functions(void); char find_user_function(const char *id); -void addBitlashFunction(const char *name, bitlash_function func_ptr); void dofunctioncall(byte); numvar func_free(void); @@ -439,7 +125,7 @@ void spb(char c); void sp(const char *); void speol(void); -numvar func_printf(void); +numvar func_printf(void); numvar func_printf_handler(byte,byte); void cmd_print(void); @@ -448,22 +134,10 @@ numvar setBaud(numvar, unumvar); void resetOutput(void); #endif -// serial override handling -#define SERIAL_OVERRIDE -#ifdef SERIAL_OVERRIDE -typedef void (*serialOutputFunc)(byte); -byte serialIsOverridden(void); -void setOutputHandler(serialOutputFunc); -void setOutputHandler(Print&); -void resetOutputHandler(void); -#endif - #ifdef ARDUINO void chkbreak(void); void cmd_print(void); #endif -numvar func_printf_handler(byte, byte); - // The Stream where input is read from and print writes to when there is // not output handler set. @@ -555,9 +229,6 @@ numvar vpop(void); // pop a numvar extern byte vsptr; #define vsempty() vsptr==0 extern numvar *arg; // argument frame pointer -numvar getVar(uint8_t id); // return value of bitlash variable. id is [0..25] for [a..z] -void assignVar(uint8_t id, numvar value); // assign value to variable. id is [0..25] for [a..z] -numvar incVar(uint8_t id); // increment variable. id is [0..25] for [a..z] // parse context types #define SCRIPT_NONE 0 @@ -566,7 +237,6 @@ numvar incVar(uint8_t id); // increment variable. id is [0..25] for [a..z] #define SCRIPT_EEPROM 3 #define SCRIPT_FILE 4 -byte findscript(const char *); byte scriptfileexists(const char *); numvar execscript(byte, numvar, const char *); void callscriptfunction(byte, numvar); @@ -583,8 +253,6 @@ void fetchc(void); void getsym(void); void traceback(void); -numvar func_fprintf(void); - const prog_char *getmsg(byte); void parsestring(void (*)(char)); void msgp(byte); @@ -594,9 +262,7 @@ void calleeprommacro(int); void getexpression(void); byte hexval(char); byte is_end(void); -numvar getarg(numvar); numvar isstring(void); -numvar getstringarg(numvar); void releaseargblock(void); void parsearglist(void); extern const prog_char reservedwords[]; @@ -649,7 +315,6 @@ numvar sdexists(void); numvar sdrm(void); numvar sdcreate(void); numvar sdappend(void); -numvar sdcat(void); numvar sdcd(void); numvar sdmd(void); numvar func_pwd(void); diff --git a/src/bitlash-public.h b/src/bitlash-public.h new file mode 100644 index 0000000..b71d1af --- /dev/null +++ b/src/bitlash-public.h @@ -0,0 +1,127 @@ +/*** + bitlash-public.h - public API + + Bitlash is a tiny language interpreter that provides a serial port shell environment + for bit banging and hardware hacking. + + See the file README for documentation. + + Bitlash lives at: http://bitlash.net + The author can be reached at: bill@bitlash.net + + Copyright (C) 2008-2012 Bill Roy + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +***/ +#ifndef _BITLASH_PUBLIC_H +#define _BITLASH_PUBLIC_H + +// bitlash-public.h declares public functions and types +// bitlash-private.h declares private (internal) functions and types +// bitlash-config.h contains (sometimes tweakable) build parameters +#include "bitlash-config.h" + +/////////////////////// +// Bitlash variables are of type "numvar" +// +// numvar is 32 bits, except for tiny builds where it is 16 bits +#if !defined(TINY_BUILD) +typedef long int numvar; +typedef unsigned long int unumvar; +#else +typedef int numvar; +typedef unsigned int unumvar; +#endif // !defined(TINY_BUILD) + +/////////////////////// +// Start Bitlash, and give it cycles to do stuff +// +void initBitlash(unsigned long baud); // start up and set baud rate +#ifndef DEFAULT_CONSOLE_ONLY +void initBitlash(Stream& stream); +#endif +void runBitlash(void); // call this in loop(), frequently + + +/////////////////////// +// Pass a command to Bitlash for interpretation +// +numvar doCommand(const char *); // execute a command from your sketch +void doCharacter(char); // pass an input character to the line editor + +/////////////////////// +// Access to Numeric Variables +// +// NOTE: access to variables a..z is via an index 0..25, not the variable names. Got it? +// +numvar getVar(unsigned char); // return value of bitlash variable. id is [0..25] for [a..z] +void assignVar(unsigned char, numvar); // assign value to variable. id is [0..25] for [a..z] +numvar incVar(unsigned char); // increment variable. id is [0..25] for [a..z] + + +/////////////////////// +// Access to the Bitlash symbol table +// +// Lookup id and return TRUE if it exists +// +byte findscript(const char *); // returns TRUE if a script exists with this ID +int getValue(const char *key); // return location of macro value in EEPROM or -1 + +/////////////////////// +// Add a user function to Bitlash +// +typedef numvar (*bitlash_function)(void); +void addBitlashFunction(const char *, bitlash_function); +numvar getarg(numvar); +numvar isstringarg(numvar); +numvar getstringarg(numvar which); + +/////////////////////// +// Serial Output Capture +// +#define SERIAL_OVERRIDE +#ifdef SERIAL_OVERRIDE +typedef void (*serialOutputFunc)(byte); +byte serialIsOverridden(void); +void setOutputHandler(serialOutputFunc); +void setOutputHandler(Print& newHandler); +void resetOutputHandler(void); +#endif +numvar func_printf_handler(byte, byte); + +#ifdef SOFTWARE_SERIAL_TX +void setOutput(byte pin); +#endif + +/////////////////////// +// File functions +// +#if defined(UNIX_BUILD) +numvar sdcat(void); +#endif +#if defined(SDFILE) || defined(UNIX_BUILD) +numvar sdwrite(const char *filename, const char *contents, byte append); +#endif +numvar func_fprintf(void); + +#endif // _BITLASH_PUBLIC_H diff --git a/src/bitlash-serial.cpp b/src/bitlash-serial.cpp index cf08c50..dbd7e8b 100644 --- a/src/bitlash-serial.cpp +++ b/src/bitlash-serial.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" #ifndef DEFAULT_CONSOLE_ONLY Stream *blconsole = &DEFAULT_CONSOLE; diff --git a/src/bitlash-taskmgr.cpp b/src/bitlash-taskmgr.cpp index 6fef279..1e529c5 100644 --- a/src/bitlash-taskmgr.cpp +++ b/src/bitlash-taskmgr.cpp @@ -33,7 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" // Background task manager diff --git a/src/bitlash-unix-file.cpp b/src/bitlash-unix-file.cpp index bd19aaf..f882685 100644 --- a/src/bitlash-unix-file.cpp +++ b/src/bitlash-unix-file.cpp @@ -76,7 +76,7 @@ ... uploads memdump as "md" ***/ -#include "bitlash.h" +#include "bitlash-private.h" #include #include #include diff --git a/src/bitlash-unix.cpp b/src/bitlash-unix.cpp index 85b47d3..d4728eb 100644 --- a/src/bitlash-unix.cpp +++ b/src/bitlash-unix.cpp @@ -26,7 +26,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "bitlash.h" +#include "bitlash-private.h" #include #include #include diff --git a/src/eeprom.cpp b/src/eeprom.cpp index 4b43fa4..77071f0 100644 --- a/src/eeprom.cpp +++ b/src/eeprom.cpp @@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE. ***/ -#include "bitlash.h" +#include "bitlash-private.h" #if defined(EEPROM_MICROCHIP_24XX32A)