Version 2.2 - 19th May 2018
Adds support for the BBC Micro Bit
This commit is contained in:
parent
c46245cce5
commit
3f60a3b70f
296
ulisp.ino
296
ulisp.ino
|
@ -1,5 +1,5 @@
|
||||||
/* uLisp SAM/SAMD Version 2.0 - www.ulisp.com
|
/* uLisp ARM Version 2.2 - www.ulisp.com
|
||||||
David Johnson-Davies - www.technoblogy.com - 10th February 2018
|
David Johnson-Davies - www.technoblogy.com - 19th May 2018
|
||||||
|
|
||||||
Licensed under the MIT license: https://opensource.org/licenses/MIT
|
Licensed under the MIT license: https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#define printfreespace
|
#define printfreespace
|
||||||
#define serialmonitor
|
#define serialmonitor
|
||||||
// #define printgcs
|
// #define printgcs
|
||||||
#define sdcardsupport
|
// #define sdcardsupport
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
|
|
||||||
|
@ -38,11 +38,11 @@
|
||||||
#define push(x, y) ((y) = cons((x),(y)))
|
#define push(x, y) ((y) = cons((x),(y)))
|
||||||
#define pop(y) ((y) = cdr(y))
|
#define pop(y) ((y) = cdr(y))
|
||||||
|
|
||||||
#define numberp(x) ((x)->type == NUMBER)
|
#define numberp(x) ((x) != NULL && (x)->type == NUMBER)
|
||||||
#define symbolp(x) ((x)->type == SYMBOL)
|
#define symbolp(x) ((x) != NULL && (x)->type == SYMBOL)
|
||||||
#define stringp(x) ((x)->type == STRING)
|
#define stringp(x) ((x) != NULL && (x)->type == STRING)
|
||||||
#define characterp(x) ((x)->type == CHARACTER)
|
#define characterp(x) ((x) != NULL && (x)->type == CHARACTER)
|
||||||
#define streamp(x) ((x)->type == STREAM)
|
#define streamp(x) ((x) != NULL && (x)->type == STREAM)
|
||||||
|
|
||||||
#define mark(x) (car(x) = (object *)(((uintptr_t)(car(x))) | MARKBIT))
|
#define mark(x) (car(x) = (object *)(((uintptr_t)(car(x))) | MARKBIT))
|
||||||
#define unmark(x) (car(x) = (object *)(((uintptr_t)(car(x))) & ~MARKBIT))
|
#define unmark(x) (car(x) = (object *)(((uintptr_t)(car(x))) & ~MARKBIT))
|
||||||
|
@ -71,7 +71,8 @@ MINUSP, ZEROP, ODDP, EVENP, CHAR, CHARCODE, CODECHAR, CHARACTERP, STRINGP, STRIN
|
||||||
STRINGGREATER, SORT, STRINGFN, CONCATENATE, SUBSEQ, READFROMSTRING, PRINCTOSTRING, PRIN1TOSTRING, LOGAND,
|
STRINGGREATER, SORT, STRINGFN, CONCATENATE, SUBSEQ, READFROMSTRING, PRINCTOSTRING, PRIN1TOSTRING, LOGAND,
|
||||||
LOGIOR, LOGXOR, LOGNOT, ASH, LOGBITP, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, READ, PRIN1, PRINT, PRINC,
|
LOGIOR, LOGXOR, LOGNOT, ASH, LOGBITP, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, READ, PRIN1, PRINT, PRINC,
|
||||||
TERPRI, READBYTE, READLINE, WRITEBYTE, WRITESTRING, WRITELINE, RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE,
|
TERPRI, READBYTE, READLINE, WRITEBYTE, WRITESTRING, WRITELINE, RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE,
|
||||||
CLS, PINMODE, DIGITALREAD, DIGITALWRITE, ANALOGREAD, ANALOGWRITE, DELAY, MILLIS, NOTE, EDIT, PPRINT, ENDFUNCTIONS };
|
CLS, PINMODE, DIGITALREAD, DIGITALWRITE, ANALOGREAD, ANALOGWRITE, DELAY, MILLIS, SLEEP, NOTE, EDIT,
|
||||||
|
PPRINT, ENDFUNCTIONS };
|
||||||
|
|
||||||
// Typedefs
|
// Typedefs
|
||||||
|
|
||||||
|
@ -130,6 +131,12 @@ typedef void (*pfun_t)(char);
|
||||||
object Workspace[WORKSPACESIZE] WORDALIGNED;
|
object Workspace[WORKSPACESIZE] WORDALIGNED;
|
||||||
uint8_t _end;
|
uint8_t _end;
|
||||||
|
|
||||||
|
#elif defined(_VARIANT_BBC_MICROBIT_)
|
||||||
|
#define WORKSPACESIZE 1024 /* Cells (8*bytes) */
|
||||||
|
#define SYMBOLTABLESIZE 512 /* Bytes */
|
||||||
|
object Workspace[WORKSPACESIZE] WORDALIGNED;
|
||||||
|
uint8_t _end;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char SymbolTable[SYMBOLTABLESIZE];
|
char SymbolTable[SYMBOLTABLESIZE];
|
||||||
|
@ -165,7 +172,7 @@ object *read ();
|
||||||
void repl(object *env);
|
void repl(object *env);
|
||||||
void printobject (object *form, pfun_t pfun);
|
void printobject (object *form, pfun_t pfun);
|
||||||
char *lookupbuiltin (symbol_t name);
|
char *lookupbuiltin (symbol_t name);
|
||||||
int lookupfn (symbol_t name);
|
intptr_t lookupfn (symbol_t name);
|
||||||
int builtin (char* n);
|
int builtin (char* n);
|
||||||
void Display (char c);
|
void Display (char c);
|
||||||
|
|
||||||
|
@ -227,6 +234,14 @@ object *symbol (symbol_t name) {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object *newsymbol (symbol_t name) {
|
||||||
|
for (int i=WORKSPACESIZE-1; i>=0; i--) {
|
||||||
|
object *obj = &Workspace[i];
|
||||||
|
if (obj->type == SYMBOL && obj->name == name) return obj;
|
||||||
|
}
|
||||||
|
return symbol(name);
|
||||||
|
}
|
||||||
|
|
||||||
object *stream (unsigned char streamtype, unsigned char address) {
|
object *stream (unsigned char streamtype, unsigned char address) {
|
||||||
object *ptr = myalloc();
|
object *ptr = myalloc();
|
||||||
ptr->type = STREAM;
|
ptr->type = STREAM;
|
||||||
|
@ -292,8 +307,8 @@ void movepointer (object *from, object *to) {
|
||||||
object *obj = &Workspace[i];
|
object *obj = &Workspace[i];
|
||||||
unsigned int type = (obj->type) & ~MARKBIT;
|
unsigned int type = (obj->type) & ~MARKBIT;
|
||||||
if (marked(obj) && (type >= STRING || type==ZERO)) {
|
if (marked(obj) && (type >= STRING || type==ZERO)) {
|
||||||
if (car(obj) == (object *)((unsigned int)from | MARKBIT))
|
if (car(obj) == (object *)((uintptr_t)from | MARKBIT))
|
||||||
car(obj) = (object *)((unsigned int)to | MARKBIT);
|
car(obj) = (object *)((uintptr_t)to | MARKBIT);
|
||||||
if (cdr(obj) == from) cdr(obj) = to;
|
if (cdr(obj) == from) cdr(obj) = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +319,7 @@ void movepointer (object *from, object *to) {
|
||||||
obj = cdr(obj);
|
obj = cdr(obj);
|
||||||
while (obj != NULL) {
|
while (obj != NULL) {
|
||||||
if (cdr(obj) == to) cdr(obj) = from;
|
if (cdr(obj) == to) cdr(obj) = from;
|
||||||
obj = (object *)((unsigned int)(car(obj)) & ~MARKBIT);
|
obj = (object *)((uintptr_t)(car(obj)) & ~MARKBIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,6 +365,7 @@ char *MakeFilename (object *arg) {
|
||||||
|
|
||||||
// Save-image and load-image
|
// Save-image and load-image
|
||||||
|
|
||||||
|
#if defined(sdcardsupport)
|
||||||
void SDWriteInt(File file, int data) {
|
void SDWriteInt(File file, int data) {
|
||||||
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
|
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
|
||||||
}
|
}
|
||||||
|
@ -358,8 +374,10 @@ void SDWritePtr(File file, uintptr_t data) {
|
||||||
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
|
file.write(data & 0xFF); file.write(data>>8 & 0xFF);
|
||||||
file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF);
|
file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int saveimage (object *arg) {
|
int saveimage (object *arg) {
|
||||||
|
#if defined(sdcardsupport)
|
||||||
SD.begin(SDCARD_SS_PIN);
|
SD.begin(SDCARD_SS_PIN);
|
||||||
File file;
|
File file;
|
||||||
if (stringp(arg)) {
|
if (stringp(arg)) {
|
||||||
|
@ -383,8 +401,12 @@ int saveimage (object *arg) {
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
return imagesize;
|
return imagesize;
|
||||||
|
#else
|
||||||
|
error(PSTR("save-image not available"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(sdcardsupport)
|
||||||
unsigned int SDReadInt (File file) {
|
unsigned int SDReadInt (File file) {
|
||||||
int lo = file.read(); int hi = file.read();
|
int lo = file.read(); int hi = file.read();
|
||||||
return lo | hi<<8;
|
return lo | hi<<8;
|
||||||
|
@ -395,8 +417,10 @@ object *SDReadPtr (File file) {
|
||||||
uintptr_t b2 = file.read(); uintptr_t b3 = file.read();
|
uintptr_t b2 = file.read(); uintptr_t b3 = file.read();
|
||||||
return (object *)(b0 | b1<<8 | b2<<16 | b3<<24);
|
return (object *)(b0 | b1<<8 | b2<<16 | b3<<24);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int loadimage (object *filename) {
|
int loadimage (object *filename) {
|
||||||
|
#if defined(sdcardsupport)
|
||||||
SD.begin(SDCARD_SS_PIN);
|
SD.begin(SDCARD_SS_PIN);
|
||||||
File file;
|
File file;
|
||||||
if (stringp(filename)) file = SD.open(MakeFilename(filename));
|
if (stringp(filename)) file = SD.open(MakeFilename(filename));
|
||||||
|
@ -418,9 +442,14 @@ int loadimage (object *filename) {
|
||||||
file.close();
|
file.close();
|
||||||
gc(NULL, NULL);
|
gc(NULL, NULL);
|
||||||
return imagesize;
|
return imagesize;
|
||||||
|
#else
|
||||||
|
error(PSTR("load-image not available"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void autorunimage () {
|
void autorunimage () {
|
||||||
|
#if defined(sdcardsupport)
|
||||||
|
SD.begin(SDCARD_SS_PIN);
|
||||||
File file = SD.open("ULISP.IMG");
|
File file = SD.open("ULISP.IMG");
|
||||||
if (!file) error(PSTR("Error: Problem autorunning from SD card"));
|
if (!file) error(PSTR("Error: Problem autorunning from SD card"));
|
||||||
object *autorun = SDReadPtr(file);
|
object *autorun = SDReadPtr(file);
|
||||||
|
@ -430,6 +459,9 @@ void autorunimage () {
|
||||||
loadimage(NULL);
|
loadimage(NULL);
|
||||||
apply(autorun, NULL, &nullenv);
|
apply(autorun, NULL, &nullenv);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
error(PSTR("autorun not available"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
|
@ -453,7 +485,6 @@ void error2 (object *symbol, PGM_P string) {
|
||||||
// Tracing
|
// Tracing
|
||||||
|
|
||||||
boolean tracing (symbol_t name) {
|
boolean tracing (symbol_t name) {
|
||||||
if (name == 0) return 0;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < TRACEMAX) {
|
while (i < TRACEMAX) {
|
||||||
if (TraceFn[i] == name) return i+1;
|
if (TraceFn[i] == name) return i+1;
|
||||||
|
@ -564,12 +595,13 @@ int issymbol (object *obj, symbol_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int eq (object *arg1, object *arg2) {
|
int eq (object *arg1, object *arg2) {
|
||||||
int same_object = (arg1 == arg2);
|
if (arg1 == arg2) return true; // Same object
|
||||||
int same_value = (arg1->cdr == arg2->cdr);
|
if ((arg1 == nil) || (arg2 == nil)) return false; // Not both values
|
||||||
int same_symbol = (symbolp(arg1) && symbolp(arg2) && same_value);
|
if (arg1->cdr != arg2->cdr) return false; // Different values
|
||||||
int same_number = (numberp(arg1) && numberp(arg2) && same_value);
|
if (symbolp(arg1) && symbolp(arg2)) return true; // Same symbol
|
||||||
int same_character = (characterp(arg1) && characterp(arg2) && same_value);
|
if (numberp(arg1) && numberp(arg2)) return true; // Same number
|
||||||
return same_object || same_symbol || same_number || same_character;
|
if (characterp(arg1) && characterp(arg2)) return true; // Same character
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int listlength (object *list) {
|
int listlength (object *list) {
|
||||||
|
@ -637,10 +669,10 @@ object *readstring (char delim, gfun_t gfun) {
|
||||||
object *obj = myalloc();
|
object *obj = myalloc();
|
||||||
obj->type = STRING;
|
obj->type = STRING;
|
||||||
int ch = gfun();
|
int ch = gfun();
|
||||||
if (ch == EOF) return nil;
|
if (ch == -1) return nil;
|
||||||
object *head = NULL;
|
object *head = NULL;
|
||||||
int chars = 0;
|
int chars = 0;
|
||||||
while ((ch != delim) && (ch != EOF)) {
|
while ((ch != delim) && (ch != -1)) {
|
||||||
if (ch == '\\') ch = gfun();
|
if (ch == '\\') ch = gfun();
|
||||||
buildstring(ch, &chars, &head);
|
buildstring(ch, &chars, &head);
|
||||||
ch = gfun();
|
ch = gfun();
|
||||||
|
@ -703,20 +735,11 @@ object *findtwin (object *var, object *env) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropframe (int tc, object **env) {
|
|
||||||
if (tc) {
|
|
||||||
while (*env != NULL && car(*env) != NULL) {
|
|
||||||
pop(*env);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
push(nil, *env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handling closures
|
// Handling closures
|
||||||
|
|
||||||
object *closure (object *fname, object *state, object *function, object *args, object **env) {
|
object *closure (int tc, object *fname, object *state, object *function, object *args, object **env) {
|
||||||
int trace = tracing(fname->name);
|
int trace = 0;
|
||||||
|
if (fname != NULL) trace = tracing(fname->name);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
indent(TraceDepth[trace-1]<<1, pserial);
|
indent(TraceDepth[trace-1]<<1, pserial);
|
||||||
pint(TraceDepth[trace-1]++, pserial);
|
pint(TraceDepth[trace-1]++, pserial);
|
||||||
|
@ -743,7 +766,9 @@ object *closure (object *fname, object *state, object *function, object *args, o
|
||||||
value = first(args);
|
value = first(args);
|
||||||
args = cdr(args);
|
args = cdr(args);
|
||||||
}
|
}
|
||||||
push(cons(var,value), *env);
|
object *pair = findtwin(var, *env);
|
||||||
|
if (tc && (pair != NULL)) cdr(pair) = value;
|
||||||
|
else push(cons(var,value), *env);
|
||||||
params = cdr(params);
|
params = cdr(params);
|
||||||
if (trace) { pserial(' '); printobject(value, pserial); }
|
if (trace) { pserial(' '); printobject(value, pserial); }
|
||||||
}
|
}
|
||||||
|
@ -765,12 +790,12 @@ object *apply (object *function, object *args, object **env) {
|
||||||
}
|
}
|
||||||
if (listp(function) && issymbol(car(function), LAMBDA)) {
|
if (listp(function) && issymbol(car(function), LAMBDA)) {
|
||||||
function = cdr(function);
|
function = cdr(function);
|
||||||
object *result = closure(NULL, NULL, function, args, env);
|
object *result = closure(0, NULL, NULL, function, args, env);
|
||||||
return eval(result, *env);
|
return eval(result, *env);
|
||||||
}
|
}
|
||||||
if (listp(function) && issymbol(car(function), CLOSURE)) {
|
if (listp(function) && issymbol(car(function), CLOSURE)) {
|
||||||
function = cdr(function);
|
function = cdr(function);
|
||||||
object *result = closure(NULL, car(function), cdr(function), args, env);
|
object *result = closure(0, NULL, car(function), cdr(function), args, env);
|
||||||
return eval(result, *env);
|
return eval(result, *env);
|
||||||
}
|
}
|
||||||
error2(function, PSTR("is an illegal function"));
|
error2(function, PSTR("is an illegal function"));
|
||||||
|
@ -823,9 +848,6 @@ inline object *cdrx (object *arg) {
|
||||||
|
|
||||||
// I2C interface
|
// I2C interface
|
||||||
|
|
||||||
uint8_t const TWI_SDA_PIN = 10;
|
|
||||||
uint8_t const TWI_SCL_PIN = 9;
|
|
||||||
|
|
||||||
void I2Cinit(bool enablePullup) {
|
void I2Cinit(bool enablePullup) {
|
||||||
(void) enablePullup;
|
(void) enablePullup;
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
|
@ -912,7 +934,9 @@ gfun_t gstreamfun (object *args) {
|
||||||
else if (streamtype == SPISTREAM) gfun = spiread;
|
else if (streamtype == SPISTREAM) gfun = spiread;
|
||||||
else if (streamtype == SERIALSTREAM) {
|
else if (streamtype == SERIALSTREAM) {
|
||||||
if (address == 0) gfun = gserial;
|
if (address == 0) gfun = gserial;
|
||||||
|
#if !defined(_VARIANT_BBC_MICROBIT_)
|
||||||
else if (address == 1) gfun = serial1read;
|
else if (address == 1) gfun = serial1read;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#if defined(sdcardsupport)
|
#if defined(sdcardsupport)
|
||||||
else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread;
|
else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread;
|
||||||
|
@ -922,7 +946,9 @@ gfun_t gstreamfun (object *args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spiwrite (char c) { SPI.transfer(c); }
|
inline void spiwrite (char c) { SPI.transfer(c); }
|
||||||
|
#if !defined(_VARIANT_BBC_MICROBIT_)
|
||||||
inline void serial1write (char c) { Serial1.write(c); }
|
inline void serial1write (char c) { Serial1.write(c); }
|
||||||
|
#endif
|
||||||
#if defined(sdcardsupport)
|
#if defined(sdcardsupport)
|
||||||
inline void SDwrite (char c) { SDpfile.write(c); }
|
inline void SDwrite (char c) { SDpfile.write(c); }
|
||||||
#endif
|
#endif
|
||||||
|
@ -939,7 +965,9 @@ pfun_t pstreamfun (object *args) {
|
||||||
else if (streamtype == SPISTREAM) pfun = spiwrite;
|
else if (streamtype == SPISTREAM) pfun = spiwrite;
|
||||||
else if (streamtype == SERIALSTREAM) {
|
else if (streamtype == SERIALSTREAM) {
|
||||||
if (address == 0) pfun = pserial;
|
if (address == 0) pfun = pserial;
|
||||||
|
#if !defined(_VARIANT_BBC_MICROBIT_)
|
||||||
else if (address == 1) pfun = serial1write;
|
else if (address == 1) pfun = serial1write;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#if defined(sdcardsupport)
|
#if defined(sdcardsupport)
|
||||||
else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite;
|
else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite;
|
||||||
|
@ -957,6 +985,8 @@ void checkanalogread (int pin) {
|
||||||
if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin"));
|
if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin"));
|
||||||
#elif defined(ARDUINO_SAMD_MKRZERO)
|
#elif defined(ARDUINO_SAMD_MKRZERO)
|
||||||
if (!(pin>=15 && pin<=21)) error(PSTR("'analogread' invalid pin"));
|
if (!(pin>=15 && pin<=21)) error(PSTR("'analogread' invalid pin"));
|
||||||
|
#elif defined(_VARIANT_BBC_MICROBIT_)
|
||||||
|
if (!((pin>=0 && pin<=4) || pin==10)) error(PSTR("'analogread' invalid pin"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,6 +997,8 @@ void checkanalogwrite (int pin) {
|
||||||
if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || pin==14)) error(PSTR("'analogwrite' invalid pin"));
|
if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || pin==14)) error(PSTR("'analogwrite' invalid pin"));
|
||||||
#elif defined(ARDUINO_SAMD_MKRZERO)
|
#elif defined(ARDUINO_SAMD_MKRZERO)
|
||||||
if (!((pin>=0 && pin<=8) || pin==10 || pin==18 || pin==19)) error(PSTR("'analogwrite' invalid pin"));
|
if (!((pin>=0 && pin<=8) || pin==10 || pin==18 || pin==19)) error(PSTR("'analogwrite' invalid pin"));
|
||||||
|
#elif defined(_VARIANT_BBC_MICROBIT_)
|
||||||
|
error(PSTR("'analogwrite' not supported"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,6 +1024,71 @@ void nonote (int pin) {
|
||||||
noTone(pin);
|
noTone(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sleep
|
||||||
|
|
||||||
|
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
|
||||||
|
void WDT_Handler(void) {
|
||||||
|
// ISR for watchdog early warning
|
||||||
|
WDT->CTRL.bit.ENABLE = 0; // Disable watchdog
|
||||||
|
while(WDT->STATUS.bit.SYNCBUSY); // Sync CTRL write
|
||||||
|
WDT->INTFLAG.bit.EW = 1; // Clear interrupt flag
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void initsleep () {
|
||||||
|
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
|
||||||
|
// One-time initialization of watchdog timer.
|
||||||
|
|
||||||
|
// Generic clock generator 2, divisor = 32 (2^(DIV+1))
|
||||||
|
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(4);
|
||||||
|
// Enable clock generator 2 using low-power 32KHz oscillator.
|
||||||
|
// With /32 divisor above, this yields 1024Hz clock.
|
||||||
|
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) |
|
||||||
|
GCLK_GENCTRL_GENEN |
|
||||||
|
GCLK_GENCTRL_SRC_OSCULP32K |
|
||||||
|
GCLK_GENCTRL_DIVSEL;
|
||||||
|
while(GCLK->STATUS.bit.SYNCBUSY);
|
||||||
|
// WDT clock = clock gen 2
|
||||||
|
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT |
|
||||||
|
GCLK_CLKCTRL_CLKEN |
|
||||||
|
GCLK_CLKCTRL_GEN_GCLK2;
|
||||||
|
|
||||||
|
// Enable WDT early-warning interrupt
|
||||||
|
NVIC_DisableIRQ(WDT_IRQn);
|
||||||
|
NVIC_ClearPendingIRQ(WDT_IRQn);
|
||||||
|
NVIC_SetPriority(WDT_IRQn, 0); // Top priority
|
||||||
|
NVIC_EnableIRQ(WDT_IRQn);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void sleep (int secs) {
|
||||||
|
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO)
|
||||||
|
WDT->CTRL.reg = 0; // Disable watchdog for config
|
||||||
|
while(WDT->STATUS.bit.SYNCBUSY);
|
||||||
|
WDT->INTENSET.bit.EW = 1; // Enable early warning interrupt
|
||||||
|
WDT->CONFIG.bit.PER = 0xB; // Period = max
|
||||||
|
WDT->CONFIG.bit.WINDOW = 0x7; // Set time of interrupt = 1024 cycles = 1 sec
|
||||||
|
WDT->CTRL.bit.WEN = 1; // Enable window mode
|
||||||
|
while(WDT->STATUS.bit.SYNCBUSY); // Sync CTRL write
|
||||||
|
|
||||||
|
SysTick->CTRL = 0; // Stop SysTick interrupts
|
||||||
|
|
||||||
|
while (secs > 0) {
|
||||||
|
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;// Clear watchdog interval
|
||||||
|
while(WDT->STATUS.bit.SYNCBUSY);
|
||||||
|
WDT->CTRL.bit.ENABLE = 1; // Start watchdog now!
|
||||||
|
while(WDT->STATUS.bit.SYNCBUSY);
|
||||||
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // Deepest sleep
|
||||||
|
__DSB();
|
||||||
|
__WFI(); // Wait for interrupt
|
||||||
|
secs--;
|
||||||
|
}
|
||||||
|
SysTick->CTRL = 7; // Restart SysTick interrupts
|
||||||
|
#else
|
||||||
|
delay(1000*secs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Special forms
|
// Special forms
|
||||||
|
|
||||||
object *sp_quote (object *args, object *env) {
|
object *sp_quote (object *args, object *env) {
|
||||||
|
@ -1013,7 +1110,9 @@ object *sp_defun (object *args, object *env) {
|
||||||
object *sp_defvar (object *args, object *env) {
|
object *sp_defvar (object *args, object *env) {
|
||||||
object *var = first(args);
|
object *var = first(args);
|
||||||
if (var->type != SYMBOL) error2(var, PSTR("is not a symbol"));
|
if (var->type != SYMBOL) error2(var, PSTR("is not a symbol"));
|
||||||
object *val = eval(second(args), env);
|
object *val = NULL;
|
||||||
|
args = cdr(args);
|
||||||
|
if (args != NULL) val = eval(first(args), env);
|
||||||
object *pair = value(var->name,GlobalEnv);
|
object *pair = value(var->name,GlobalEnv);
|
||||||
if (pair != NULL) { cdr(pair) = val; return var; }
|
if (pair != NULL) { cdr(pair) = val; return var; }
|
||||||
push(cons(var, val), GlobalEnv);
|
push(cons(var, val), GlobalEnv);
|
||||||
|
@ -1271,7 +1370,7 @@ object *sp_withsdcard (object *args, object *env) {
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
if (params != NULL && first(params) != NULL) mode = integer(first(params));
|
if (params != NULL && first(params) != NULL) mode = integer(first(params));
|
||||||
int oflag = O_READ;
|
int oflag = O_READ;
|
||||||
if (mode == 1) oflag = O_RDWR | O_CREAT; else if (mode == 2) oflag = O_RDWR | O_CREAT | O_TRUNC;
|
if (mode == 1) oflag = O_RDWR | O_CREAT | O_APPEND; else if (mode == 2) oflag = O_RDWR | O_CREAT | O_TRUNC;
|
||||||
if (mode >= 1) {
|
if (mode >= 1) {
|
||||||
SDpfile = SD.open(MakeFilename(filename), oflag);
|
SDpfile = SD.open(MakeFilename(filename), oflag);
|
||||||
if (!SDpfile) error(PSTR("Problem writing to SD card"));
|
if (!SDpfile) error(PSTR("Problem writing to SD card"));
|
||||||
|
@ -1391,17 +1490,20 @@ object *fn_consp (object *args, object *env) {
|
||||||
|
|
||||||
object *fn_numberp (object *args, object *env) {
|
object *fn_numberp (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
return numberp(first(args)) ? tee : nil;
|
object *arg = first(args);
|
||||||
|
return numberp(arg) ? tee : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_symbolp (object *args, object *env) {
|
object *fn_symbolp (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
return symbolp(first(args)) ? tee : nil;
|
object *arg = first(args);
|
||||||
|
return symbolp(arg) ? tee : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_streamp (object *args, object *env) {
|
object *fn_streamp (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
return streamp(first(args)) ? tee : nil;
|
object *arg = first(args);
|
||||||
|
return streamp(arg) ? tee : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_eq (object *args, object *env) {
|
object *fn_eq (object *args, object *env) {
|
||||||
|
@ -1587,8 +1689,6 @@ object *fn_mapc (object *args, object *env) {
|
||||||
if (list2 != NULL) {
|
if (list2 != NULL) {
|
||||||
list2 = car(list2);
|
list2 = car(list2);
|
||||||
if (!listp(list2)) error(PSTR("'mapc' third argument is not a list"));
|
if (!listp(list2)) error(PSTR("'mapc' third argument is not a list"));
|
||||||
}
|
|
||||||
if (list2 != NULL) {
|
|
||||||
while (list1 != NULL && list2 != NULL) {
|
while (list1 != NULL && list2 != NULL) {
|
||||||
apply(function, cons(car(list1),cons(car(list2),NULL)), &env);
|
apply(function, cons(car(list1),cons(car(list2),NULL)), &env);
|
||||||
list1 = cdr(list1);
|
list1 = cdr(list1);
|
||||||
|
@ -1768,7 +1868,8 @@ object *fn_max (object *args, object *env) {
|
||||||
int result = integer(first(args));
|
int result = integer(first(args));
|
||||||
args = cdr(args);
|
args = cdr(args);
|
||||||
while (args != NULL) {
|
while (args != NULL) {
|
||||||
result = max(result,integer(car(args)));
|
int next = integer(car(args));
|
||||||
|
if (next > result) result = next;
|
||||||
args = cdr(args);
|
args = cdr(args);
|
||||||
}
|
}
|
||||||
return number(result);
|
return number(result);
|
||||||
|
@ -1779,7 +1880,8 @@ object *fn_min (object *args, object *env) {
|
||||||
int result = integer(first(args));
|
int result = integer(first(args));
|
||||||
args = cdr(args);
|
args = cdr(args);
|
||||||
while (args != NULL) {
|
while (args != NULL) {
|
||||||
result = min(result,integer(car(args)));
|
int next = integer(car(args));
|
||||||
|
if (next < result) result = next;
|
||||||
args = cdr(args);
|
args = cdr(args);
|
||||||
}
|
}
|
||||||
return number(result);
|
return number(result);
|
||||||
|
@ -2076,7 +2178,7 @@ int gstr () {
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
char c = nthchar(GlobalString, GlobalStringIndex++);
|
char c = nthchar(GlobalString, GlobalStringIndex++);
|
||||||
return (c != 0) ? c : '\n';
|
return (c != 0) ? c : '\n'; // -1?
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_readfromstring (object *args, object *env) {
|
object *fn_readfromstring (object *args, object *env) {
|
||||||
|
@ -2253,7 +2355,7 @@ object *fn_readbyte (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
gfun_t gfun = gstreamfun(args);
|
gfun_t gfun = gstreamfun(args);
|
||||||
int c = gfun();
|
int c = gfun();
|
||||||
return (c == EOF) ? nil : number(c);
|
return (c == -1) ? nil : number(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_readline (object *args, object *env) {
|
object *fn_readline (object *args, object *env) {
|
||||||
|
@ -2288,7 +2390,7 @@ object *fn_writeline (object *args, object *env) {
|
||||||
char temp = PrintReadably;
|
char temp = PrintReadably;
|
||||||
PrintReadably = 0;
|
PrintReadably = 0;
|
||||||
printstring(obj, pfun);
|
printstring(obj, pfun);
|
||||||
(pfun)('\n');
|
pln(pfun);
|
||||||
PrintReadably = temp;
|
PrintReadably = temp;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2420,7 @@ object *fn_gc (object *obj, object *env) {
|
||||||
pint(Freespace - initial, pserial);
|
pint(Freespace - initial, pserial);
|
||||||
pfstring(PSTR(" bytes, Time: "), pserial);
|
pfstring(PSTR(" bytes, Time: "), pserial);
|
||||||
pint(elapsed, pserial);
|
pint(elapsed, pserial);
|
||||||
pfstring(PSTR(" uS\r"), pserial);
|
pfstring(PSTR(" us\r"), pserial);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2338,7 +2440,7 @@ object *fn_loadimage (object *args, object *env) {
|
||||||
return number(loadimage(args));
|
return number(loadimage(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_cls(object *args, object *env) {
|
object *fn_cls (object *args, object *env) {
|
||||||
(void) args, (void) env;
|
(void) args, (void) env;
|
||||||
pserial(12);
|
pserial(12);
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -2358,14 +2460,15 @@ object *fn_pinmode (object *args, object *env) {
|
||||||
object *fn_digitalread (object *args, object *env) {
|
object *fn_digitalread (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
int pin = integer(first(args));
|
int pin = integer(first(args));
|
||||||
if(digitalRead(pin) != 0) return tee; else return nil;
|
if (digitalRead(pin) != 0) return tee; else return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *fn_digitalwrite (object *args, object *env) {
|
object *fn_digitalwrite (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
int pin = integer(first(args));
|
int pin = integer(first(args));
|
||||||
object *mode = second(args);
|
object *mode = second(args);
|
||||||
digitalWrite(pin, (mode != nil));
|
if (numberp(mode)) digitalWrite(pin, mode->integer);
|
||||||
|
else digitalWrite(pin, (mode != nil));
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2397,12 +2500,20 @@ object *fn_millis (object *args, object *env) {
|
||||||
return number(millis());
|
return number(millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object *fn_sleep (object *args, object *env) {
|
||||||
|
(void) env;
|
||||||
|
object *arg1 = first(args);
|
||||||
|
sleep(integer(arg1));
|
||||||
|
return arg1;
|
||||||
|
}
|
||||||
|
|
||||||
object *fn_note (object *args, object *env) {
|
object *fn_note (object *args, object *env) {
|
||||||
(void) env;
|
(void) env;
|
||||||
static int pin = 255;
|
static int pin = 255;
|
||||||
if (args != NULL) {
|
if (args != NULL) {
|
||||||
pin = integer(first(args));
|
pin = integer(first(args));
|
||||||
int note = integer(second(args));
|
int note = 0;
|
||||||
|
if (cddr(args) != NULL) note = integer(second(args));
|
||||||
int octave = 0;
|
int octave = 0;
|
||||||
if (cddr(args) != NULL) octave = integer(third(args));
|
if (cddr(args) != NULL) octave = integer(third(args));
|
||||||
playnote(pin, note, octave);
|
playnote(pin, note, octave);
|
||||||
|
@ -2486,8 +2597,9 @@ void superprint (object *form, int lm, pfun_t pfun) {
|
||||||
else supersub(form, lm + PPINDENT, 1, pfun);
|
else supersub(form, lm + PPINDENT, 1, pfun);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ppspecials = 12;
|
const int ppspecials = 14;
|
||||||
const char ppspecial[ppspecials] PROGMEM = { IF, SETQ, TEE, LET, LETSTAR, LAMBDA, WHEN, UNLESS, WITHI2C, WITHSERIAL, WITHSPI, WITHSDCARD };
|
const char ppspecial[ppspecials] PROGMEM =
|
||||||
|
{ DOTIMES, DOLIST, IF, SETQ, TEE, LET, LETSTAR, LAMBDA, WHEN, UNLESS, WITHI2C, WITHSERIAL, WITHSPI, WITHSDCARD };
|
||||||
|
|
||||||
void supersub (object *form, int lm, int super, pfun_t pfun) {
|
void supersub (object *form, int lm, int super, pfun_t pfun) {
|
||||||
int special = 0, separate = 1;
|
int special = 0, separate = 1;
|
||||||
|
@ -2673,9 +2785,10 @@ const char string145[] PROGMEM = "analogread";
|
||||||
const char string146[] PROGMEM = "analogwrite";
|
const char string146[] PROGMEM = "analogwrite";
|
||||||
const char string147[] PROGMEM = "delay";
|
const char string147[] PROGMEM = "delay";
|
||||||
const char string148[] PROGMEM = "millis";
|
const char string148[] PROGMEM = "millis";
|
||||||
const char string149[] PROGMEM = "note";
|
const char string149[] PROGMEM = "sleep";
|
||||||
const char string150[] PROGMEM = "edit";
|
const char string150[] PROGMEM = "note";
|
||||||
const char string151[] PROGMEM = "pprint";
|
const char string151[] PROGMEM = "edit";
|
||||||
|
const char string152[] PROGMEM = "pprint";
|
||||||
|
|
||||||
const tbl_entry_t lookup_table[] PROGMEM = {
|
const tbl_entry_t lookup_table[] PROGMEM = {
|
||||||
{ string0, NULL, NIL, NIL },
|
{ string0, NULL, NIL, NIL },
|
||||||
|
@ -2827,9 +2940,10 @@ const tbl_entry_t lookup_table[] PROGMEM = {
|
||||||
{ string146, fn_analogwrite, 2, 2 },
|
{ string146, fn_analogwrite, 2, 2 },
|
||||||
{ string147, fn_delay, 1, 1 },
|
{ string147, fn_delay, 1, 1 },
|
||||||
{ string148, fn_millis, 0, 0 },
|
{ string148, fn_millis, 0, 0 },
|
||||||
{ string149, fn_note, 0, 3 },
|
{ string149, fn_sleep, 1, 1 },
|
||||||
{ string150, fn_edit, 1, 1 },
|
{ string150, fn_note, 0, 3 },
|
||||||
{ string151, fn_pprint, 1, 2 },
|
{ string151, fn_edit, 1, 1 },
|
||||||
|
{ string152, fn_pprint, 1, 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Table lookup functions
|
// Table lookup functions
|
||||||
|
@ -2837,7 +2951,7 @@ const tbl_entry_t lookup_table[] PROGMEM = {
|
||||||
int builtin (char* n) {
|
int builtin (char* n) {
|
||||||
int entry = 0;
|
int entry = 0;
|
||||||
while (entry < ENDFUNCTIONS) {
|
while (entry < ENDFUNCTIONS) {
|
||||||
if(strcmp_P(n, (char*)pgm_read_word(&lookup_table[entry].string)) == 0)
|
if (strcmp_P(n, (char*)pgm_read_word(&lookup_table[entry].string)) == 0)
|
||||||
return entry;
|
return entry;
|
||||||
entry++;
|
entry++;
|
||||||
}
|
}
|
||||||
|
@ -2858,7 +2972,7 @@ int longsymbol (char *buffer) {
|
||||||
return i + 64000; // First number unused by radix40
|
return i + 64000; // First number unused by radix40
|
||||||
}
|
}
|
||||||
|
|
||||||
int lookupfn (symbol_t name) {
|
intptr_t lookupfn (symbol_t name) {
|
||||||
return pgm_read_word(&lookup_table[name].fptr);
|
return pgm_read_word(&lookup_table[name].fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2904,8 +3018,8 @@ object *eval (object *form, object *env) {
|
||||||
int TC=0;
|
int TC=0;
|
||||||
EVAL:
|
EVAL:
|
||||||
// Enough space?
|
// Enough space?
|
||||||
if (Freespace < 20) gc(form, env);
|
|
||||||
if (End != 0xA5) error(PSTR("Stack overflow"));
|
if (End != 0xA5) error(PSTR("Stack overflow"));
|
||||||
|
if (Freespace < 20) gc(form, env);
|
||||||
// Escape
|
// Escape
|
||||||
if (tstflag(ESCAPE)) { clrflag(ESCAPE); error(PSTR("Escape!"));}
|
if (tstflag(ESCAPE)) { clrflag(ESCAPE); error(PSTR("Escape!"));}
|
||||||
#if defined (serialmonitor)
|
#if defined (serialmonitor)
|
||||||
|
@ -2944,8 +3058,9 @@ object *eval (object *form, object *env) {
|
||||||
push(newenv, GCStack);
|
push(newenv, GCStack);
|
||||||
while (assigns != NULL) {
|
while (assigns != NULL) {
|
||||||
object *assign = car(assigns);
|
object *assign = car(assigns);
|
||||||
if (consp(assign)) push(cons(first(assign),eval(second(assign),env)), newenv);
|
if (!consp(assign)) push(cons(assign,nil), newenv);
|
||||||
else push(cons(assign,nil), newenv);
|
else if (cdr(assign) == NULL) push(cons(first(assign),nil), newenv);
|
||||||
|
else push(cons(first(assign),eval(second(assign),env)), newenv);
|
||||||
car(GCStack) = newenv;
|
car(GCStack) = newenv;
|
||||||
if (name == LETSTAR) env = newenv;
|
if (name == LETSTAR) env = newenv;
|
||||||
assigns = cdr(assigns);
|
assigns = cdr(assigns);
|
||||||
|
@ -3014,8 +3129,7 @@ object *eval (object *form, object *env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listp(function) && issymbol(car(function), LAMBDA)) {
|
if (listp(function) && issymbol(car(function), LAMBDA)) {
|
||||||
dropframe(TCstart, &env);
|
form = closure(TCstart, fname, NULL, cdr(function), args, &env);
|
||||||
form = closure(fname, NULL, cdr(function), args, &env);
|
|
||||||
pop(GCStack);
|
pop(GCStack);
|
||||||
int trace = tracing(fname->name);
|
int trace = tracing(fname->name);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
|
@ -3034,8 +3148,7 @@ object *eval (object *form, object *env) {
|
||||||
|
|
||||||
if (listp(function) && issymbol(car(function), CLOSURE)) {
|
if (listp(function) && issymbol(car(function), CLOSURE)) {
|
||||||
function = cdr(function);
|
function = cdr(function);
|
||||||
dropframe(TCstart, &env);
|
form = closure(TCstart, fname, car(function), cdr(function), args, &env);
|
||||||
form = closure(fname, car(function), cdr(function), args, &env);
|
|
||||||
pop(GCStack);
|
pop(GCStack);
|
||||||
TC = 1;
|
TC = 1;
|
||||||
goto EVAL;
|
goto EVAL;
|
||||||
|
@ -3088,7 +3201,7 @@ void printstring (object *form, pfun_t pfun) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pfstring (PGM_P s, pfun_t pfun) {
|
void pfstring (PGM_P s, pfun_t pfun) {
|
||||||
int p = (int)s;
|
intptr_t p = (intptr_t)s;
|
||||||
while (1) {
|
while (1) {
|
||||||
char c = pgm_read_byte(p++);
|
char c = pgm_read_byte(p++);
|
||||||
if (c == 0) return;
|
if (c == 0) return;
|
||||||
|
@ -3119,7 +3232,7 @@ void pfl (pfun_t pfun) {
|
||||||
if (LastPrint != '\n') pfun('\n');
|
if (LastPrint != '\n') pfun('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
void printobject(object *form, pfun_t pfun){
|
void printobject (object *form, pfun_t pfun){
|
||||||
if (form == NULL) pfstring(PSTR("nil"), pfun);
|
if (form == NULL) pfstring(PSTR("nil"), pfun);
|
||||||
else if (listp(form) && issymbol(car(form), CLOSURE)) pfstring(PSTR("<closure>"), pfun);
|
else if (listp(form) && issymbol(car(form), CLOSURE)) pfstring(PSTR("<closure>"), pfun);
|
||||||
else if (listp(form)) {
|
else if (listp(form)) {
|
||||||
|
@ -3180,7 +3293,8 @@ object *nextitem (gfun_t gfun) {
|
||||||
ch = '(';
|
ch = '(';
|
||||||
}
|
}
|
||||||
if (ch == '\n') ch = gfun();
|
if (ch == '\n') ch = gfun();
|
||||||
if (ch == EOF) return nil;
|
if (ch == EOF) exit(0);
|
||||||
|
if (ch == -1) return nil;
|
||||||
if (ch == ')') return (object *)KET;
|
if (ch == ')') return (object *)KET;
|
||||||
if (ch == '(') return (object *)BRA;
|
if (ch == '(') return (object *)BRA;
|
||||||
if (ch == '\'') return (object *)QUO;
|
if (ch == '\'') return (object *)QUO;
|
||||||
|
@ -3189,7 +3303,7 @@ object *nextitem (gfun_t gfun) {
|
||||||
// Parse string
|
// Parse string
|
||||||
if (ch == '"') return readstring('"', gfun);
|
if (ch == '"') return readstring('"', gfun);
|
||||||
|
|
||||||
// Parse variable, character, or number
|
// Parse symbol, character, or number
|
||||||
int index = 0, base = 10, sign = 1;
|
int index = 0, base = 10, sign = 1;
|
||||||
char *buffer = SymbolTop;
|
char *buffer = SymbolTop;
|
||||||
int bufmax = SYMBOLTABLESIZE-(buffer-SymbolTable)-1; // Max index
|
int bufmax = SYMBOLTABLESIZE-(buffer-SymbolTable)-1; // Max index
|
||||||
|
@ -3211,7 +3325,7 @@ object *nextitem (gfun_t gfun) {
|
||||||
ch = gfun();
|
ch = gfun();
|
||||||
}
|
}
|
||||||
int isnumber = (digitvalue(ch)<base);
|
int isnumber = (digitvalue(ch)<base);
|
||||||
buffer[2] = '\0'; // In case variable is one letter
|
buffer[2] = '\0'; // In case symbol is one letter
|
||||||
|
|
||||||
while(!isspace(ch) && ch != ')' && ch != '(' && index < bufmax) {
|
while(!isspace(ch) && ch != ')' && ch != '(' && index < bufmax) {
|
||||||
buffer[index++] = ch;
|
buffer[index++] = ch;
|
||||||
|
@ -3222,8 +3336,7 @@ object *nextitem (gfun_t gfun) {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[index] = '\0';
|
buffer[index] = '\0';
|
||||||
if (ch == ')') LastChar = ')';
|
if (ch == ')' || ch == '(') LastChar = ch;
|
||||||
if (ch == '(') LastChar = '(';
|
|
||||||
|
|
||||||
if (isnumber) {
|
if (isnumber) {
|
||||||
if (base == 10 && result > ((unsigned int)INT_MAX+(1-sign)/2))
|
if (base == 10 && result > ((unsigned int)INT_MAX+(1-sign)/2))
|
||||||
|
@ -3241,9 +3354,9 @@ object *nextitem (gfun_t gfun) {
|
||||||
|
|
||||||
int x = builtin(buffer);
|
int x = builtin(buffer);
|
||||||
if (x == NIL) return nil;
|
if (x == NIL) return nil;
|
||||||
if (x < ENDFUNCTIONS) return symbol(x);
|
if (x < ENDFUNCTIONS) return newsymbol(x);
|
||||||
else if (index < 4 && valid40(buffer)) return symbol(pack40(buffer));
|
else if (index < 4 && valid40(buffer)) return newsymbol(pack40(buffer));
|
||||||
else return symbol(longsymbol(buffer));
|
else return newsymbol(longsymbol(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
object *readrest (gfun_t gfun) {
|
object *readrest (gfun_t gfun) {
|
||||||
|
@ -3282,17 +3395,17 @@ object *read (gfun_t gfun) {
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
|
|
||||||
void initenv() {
|
void initenv () {
|
||||||
GlobalEnv = NULL;
|
GlobalEnv = NULL;
|
||||||
tee = symbol(TEE);
|
tee = symbol(TEE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup () {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
while (!Serial); // wait for Serial to initialize
|
|
||||||
initworkspace();
|
initworkspace();
|
||||||
initenv();
|
initenv();
|
||||||
pfstring(PSTR("uLisp 2.0 "), pserial); pln(pserial);
|
initsleep();
|
||||||
|
pfstring(PSTR("uLisp 2.2 "), pserial); pln(pserial);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read/Evaluate/Print loop
|
// Read/Evaluate/Print loop
|
||||||
|
@ -3324,13 +3437,16 @@ void repl (object *env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop () {
|
void loop () {
|
||||||
|
End = 0xA5; // Canary to check stack
|
||||||
if (!setjmp(exception)) {
|
if (!setjmp(exception)) {
|
||||||
#if defined(resetautorun)
|
#if defined(resetautorun)
|
||||||
autorunimage();
|
volatile int autorun = 12; // Fudge to keep code size the same
|
||||||
|
#else
|
||||||
|
volatile int autorun = 13;
|
||||||
#endif
|
#endif
|
||||||
|
if (autorun == 12) autorunimage();
|
||||||
}
|
}
|
||||||
// Come here after error
|
// Come here after error
|
||||||
End = 0xA5; // Canary to check stack
|
|
||||||
for (int i=0; i<TRACEMAX; i++) TraceDepth[i] = 0;
|
for (int i=0; i<TRACEMAX; i++) TraceDepth[i] = 0;
|
||||||
#if defined(sdcardsupport)
|
#if defined(sdcardsupport)
|
||||||
SDpfile.close(); SDgfile.close();
|
SDpfile.close(); SDgfile.close();
|
||||||
|
|
Loading…
Reference in New Issue