From 86411d214de8abb00cc8cb4241b7e76badd47afc Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Mon, 28 Apr 2025 21:23:12 -0700 Subject: [PATCH] update to new picocalc release. --- LICENSE | 22 + README.org | 9 +- picocalc/picocalc.ino | 4024 +++++++++++---------------------- picocalc/ulisp-extensions.ino | 994 -------- 4 files changed, 1335 insertions(+), 3714 deletions(-) create mode 100644 LICENSE delete mode 100644 picocalc/ulisp-extensions.ino diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5cd79ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2025 Kyle Isom +Copyright (c) 2021 David Johnson-Davies + +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. \ No newline at end of file diff --git a/README.org b/README.org index ab9a4df..b931907 100644 --- a/README.org +++ b/README.org @@ -13,7 +13,8 @@ ** Platforms -*** picocalc: -*** teensy: -*** t-deck -*** builder + + + picocalc + + teensy + + t-deck + + builder diff --git a/picocalc/picocalc.ino b/picocalc/picocalc.ino index 32ab147..5f4fb1d 100644 --- a/picocalc/picocalc.ino +++ b/picocalc/picocalc.ino @@ -1,59 +1,60 @@ -/* uLisp ARM Release 4.7b - www.ulisp.com - David Johnson-Davies - www.technoblogy.com - 20th March 2025 - +/* uLisp PicoCalc Release 4.7d - www.ulisp.com + David Johnson-Davies - www.technoblogy.com - 28th April 2025 + Licensed under the MIT license: https://opensource.org/licenses/MIT */ // Lisp Library -// Loaded from LispLibrary.h -// const char LispLibrary[] PROGMEM = ""; +// const char LispLibrary[] = ""; // Compile options +#define PLATFORM_PICOCALC + #define resetautorun #define printfreespace +#define serialmonitor // #define printgcs #define sdcardsupport -#define gfxsupport +#define gfxsupport // Need this for PicoCalc #define lisplibrary -#define assemblerlist -#define lineeditor -#define vt100 +// #define assemblerlist #define extensions -#define PLATFORM_PICOCALC 1 -#define i2ckbd -#define BAUDRATE 96 - // Includes #include "LispLibrary.h" - #include #include #include #include -#if defined(ARDUINO_RASPBERRY_PI_PICO) || \ - defined(ARDUINO_RASPBERRY_PI_PICO_2W) || \ - defined(ARDUINO_RASPBERRY_PI_PICO_W) || \ - defined(ARDUINO_RASPBERRY_PI_PICO_2) -#define RASPBERRY_PI_PICO_PLATFORM -#if defined(PLATFORM_PICOCALC) -#define IS_PICOCALC -#endif -#endif - #if defined(sdcardsupport) -#if defined(RASPBERRY_PI_PICO_PLATFORM) - #include -#endif #include +#define SDCARD_SS_PIN 17 #define SDSIZE 720 #else #define SDSIZE 0 #endif +// PicoCalc LittleFS support +#define LITTLEFS +#include +#define FS_FILE_WRITE "w" +#define FS_FILE_READ "r" + +// PicoCalc keyboard, display, and sound support +const int COLOR_WHITE = 0xffff, COLOR_BLACK = 0; +#include +#include +PCKeyboard pc_kbd; +#define Serial Serial1 // Comment out to use the Raspberry Pi Pico micro USB port +const int KEY_ESC = 0xB1; +TFT_eSPI tft = TFT_eSPI(320,320); +#include "hardware/pwm.h" +#define AUDIO_PIN_L 26 +#define AUDIO_PIN_R 27 + // Platform specific settings #define WORDALIGNED __attribute__((aligned (4))) @@ -61,219 +62,20 @@ #define RAMFUNC __attribute__ ((section (".ramfunctions"))) #define MEMBANK -// ATSAMD21 boards *************************************************************** - -#if defined(ARDUINO_GEMMA_M0) || defined(ARDUINO_SEEED_XIAO_M0) || defined(ARDUINO_QTPY_M0) - #define WORKSPACESIZE (2816-SDSIZE) /* Objects (8*bytes) */ - #define CPUFLASH - #define FLASHSIZE 32768 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define CPU_ATSAMD21 - -#elif defined(ARDUINO_ITSYBITSY_M0) || defined(ARDUINO_SAMD_FEATHER_M0_EXPRESS) - #define WORKSPACESIZE (2816-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define SDCARD_SS_PIN 4 - #define CPU_ATSAMD21 - -#elif defined(ADAFRUIT_FEATHER_M0) /* Feather M0 without DataFlash */ - #define WORKSPACESIZE (2816-SDSIZE) /* Objects (8*bytes) */ - #define CPUFLASH - #define FLASHSIZE 32768 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define SDCARD_SS_PIN 4 - #define CPU_ATSAMD21 - -#elif defined(ARDUINO_SAMD_MKRZERO) - #define WORKSPACESIZE (2640-SDSIZE) /* Objects (8*bytes) */ - #define CPUFLASH - #define FLASHSIZE 32768 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 840 - #define CPU_ATSAMD21 - -#elif defined(ARDUINO_SAMD_ZERO) /* Put this last, otherwise overrides the Adafruit boards */ - #define WORKSPACESIZE (2500-SDSIZE) /* Objects (8*bytes) */ - #define CPUFLASH - #define FLASHSIZE 32768 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define SDCARD_SS_PIN 10 - #define CPU_ATSAMD21 - -// ATSAMD51 boards *************************************************************** - -#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4) - #define WORKSPACESIZE (20608-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 400 - #define SDCARD_SS_PIN 10 - #define CPU_ATSAMD51 - -#elif defined(ARDUINO_PYBADGE_M4) || defined(ARDUINO_PYGAMER_M4) - #define WORKSPACESIZE (20608-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 400 - #define SDCARD_SS_PIN 10 - #define CPU_ATSAMD51 - #if defined(gfxsupport) - const int TFT_BACKLIGHT = 47; - #include // Core graphics library - #include // Hardware-specific library for ST7735 - Adafruit_ST7735 tft = Adafruit_ST7735(44, 45, 41, 42, 46); - #endif - -#elif defined(ARDUINO_WIO_TERMINAL) - #define WORKSPACESIZE (20480-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 400 - #define CPU_ATSAMD51 - #define EXTERNAL_FLASH_USE_QSPI - #if defined(gfxsupport) - #include // Hardware-specific library - TFT_eSPI tft = TFT_eSPI(); - #endif - -#elif defined(ARDUINO_GRAND_CENTRAL_M4) - #define WORKSPACESIZE (28800-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 8192000 /* 8 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 440 - #define CPU_ATSAMD51 - -// nRF51 boards *************************************************************** - -#elif defined(ARDUINO_BBC_MICROBIT) || defined(ARDUINO_SINOBIT) - #define WORKSPACESIZE 1344 /* Objects (8*bytes) */ - #define CODESIZE 64 /* Bytes */ - #define STACKDIFF 320 - #define CPU_NRF51822 - -#elif defined(ARDUINO_CALLIOPE_MINI) - #define WORKSPACESIZE 3392 /* Objects (8*bytes) */ - #define CODESIZE 64 /* Bytes */ - #define STACKDIFF 320 - #define CPU_NRF51822 - -// nRF52 boards *************************************************************** - -#elif defined(ARDUINO_BBC_MICROBIT_V2) - #define WORKSPACESIZE 12928 /* Objects (8*bytes) */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define CPU_NRF52833 - -#elif defined(ARDUINO_NRF52840_ITSYBITSY) || defined(ARDUINO_Seeed_XIAO_nRF52840) \ - || defined(ARDUINO_Seeed_XIAO_nRF52840_Sense) || defined(ARDUINO_NRF52840_CIRCUITPLAY) - #define WORKSPACESIZE (21120-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 8 - #define CPU_NRF52840 - -#elif defined(ARDUINO_NRF52840_CLUE) - #define WORKSPACESIZE (21120-SDSIZE) /* Objects (8*bytes) */ - #define DATAFLASH - #define FLASHSIZE 2048000 /* 2 MBytes */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 8 - #define CPU_NRF52840 - #if defined(gfxsupport) - #include - #include - Adafruit_ST7789 tft = Adafruit_ST7789(&SPI1, PIN_TFT_CS, PIN_TFT_DC, PIN_TFT_RST); - #endif - -// MAX32620 boards *************************************************************** - -#elif defined(MAX32620) - #define WORKSPACESIZE (24704-SDSIZE) /* Objects (8*bytes) */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 320 - #define CPU_MAX32620 - #define Wire1 Wire2 - -// iMXRT1062 boards *************************************************************** - -#elif defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) - #define WORKSPACESIZE 60000 /* Objects (8*bytes) */ - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 15000 - #define LITTLEFS (960 * 1024) - #include - LittleFS_Program LittleFS; - #define FS_FILE_WRITE FILE_WRITE_BEGIN - #define FS_FILE_READ FILE_READ - #define CPU_iMXRT1062 - #define SDCARD_SS_PIN BUILTIN_SDCARD - #define BitOrder uint8_t - #undef RAMFUNC - #define RAMFUNC FASTRUN - #undef MEMBANK - #define MEMBANK DMAMEM +// These five boards are compatible with PicoCalc (H versions are supplied with header pins soldered in): // RP2040 boards *************************************************************** -#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) \ - || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040) +#if defined(ARDUINO_RASPBERRY_PI_PICO) #define WORKSPACESIZE (23000-SDSIZE) /* Objects (8*bytes) */ - - #if defined(sdcardsupport) - #define SDCARD_SS_PIN 17 - #else - #define LITTLEFS - #include - #define FILE_WRITE_BEGIN "w" - #define FILE_READ "r" - #endif - - #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 320 - #define CPU_RP2040 - #if defined(gfxsupport) - #include // Hardware-specific library - #if defined(PLATFORM_PICOCALC) - #include - PCKeyboard pc_kbd; - TFT_eSPI tft = TFT_eSPI(320,320); - #else - TFT_eSPI tft = TFT_eSPI(); - #endif - #endif - -#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) - #define WORKSPACESIZE 23000 /* Objects (8*bytes) */ #define CODESIZE 256 /* Bytes */ - #define STACKDIFF 480 - #define LITTLEFS - #include - #define FS_FILE_WRITE "w" - #define FS_FILE_READ "r" - #define SDCARD_SS_PIN 23 + #define STACKDIFF 320 #define CPU_RP2040 #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) #define WORKSPACESIZE (15232-SDSIZE) /* Objects (8*bytes) */ #define CODESIZE 256 /* Bytes */ #define STACKDIFF 480 - #define LITTLEFS - #include - #include - #define FS_FILE_WRITE "w" - #define FS_FILE_READ "r" #define CPU_RP2040 // RP2350 boards *************************************************************** @@ -287,10 +89,6 @@ #define STACKDIFF 520 #endif #define CODESIZE 256 /* Bytes */ - #define LITTLEFS - #include - #define FS_FILE_WRITE "w" - #define FS_FILE_READ "r" #define CPU_RP2350 #elif defined(ARDUINO_RASPBERRY_PI_PICO_2W) @@ -302,31 +100,8 @@ #define STACKDIFF 520 #endif #define CODESIZE 256 /* Bytes */ - #define LITTLEFS #include - // #include - #if defined(sdcardsupport) - #define SDCARD_SS_PIN 17 - #else - #define LITTLEFS - #include - #define FILE_WRITE_BEGIN "w" - #define FILE_READ "r" - #endif - #define FS_FILE_WRITE "w" - #define FS_FILE_READ "r" - #define CPU_RP2350j - #if defined(gfxsupport) - #include // Hardware-specific library - #if defined(PLATFORM_PICOCALC) - #include - PCKeyboard pc_kbd; - TFT_eSPI tft = TFT_eSPI(320,320); - #else - TFT_eSPI tft = TFT_eSPI(); - #endif - #endif - + #define CPU_RP2350 #elif defined(ARDUINO_PIMORONI_PICO_PLUS_2) //#define BOARD_HAS_PSRAM /* Uncomment to use PSRAM */ @@ -350,60 +125,10 @@ #define SDCARD_SS_PIN 10 #define CPU_RP2350 -#elif defined(ARDUINO_PIMORONI_TINY2350) - #if defined(__riscv) - #define WORKSPACESIZE (42500-SDSIZE) /* Objects (8*bytes) */ - #define STACKDIFF 580 - #else - #define WORKSPACESIZE (47000-SDSIZE) /* Objects (8*bytes) */ - #define STACKDIFF 520 - #endif - #define CODESIZE 256 /* Bytes */ - #define LITTLEFS - #include - #define FS_FILE_WRITE "w" - #define FS_FILE_READ "r" - #define CPU_RP2350 - -// RA4M1 boards *************************************************************** - -#elif defined(ARDUINO_MINIMA) - #define WORKSPACESIZE (2032-SDSIZE) /* Objects (8*bytes) */ - #include - #define EEPROMFLASH - #define FLASHSIZE 8192 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define eAnalogReference ar_aref - #define CPU_RA4M1 - #define SDCARD_SS_PIN 10 - -#elif defined(ARDUINO_UNOWIFIR4) - #define WORKSPACESIZE (1610-SDSIZE) /* Objects (8*bytes) */ - #include - #include "WiFiS3.h" - #define EEPROMFLASH - #define FLASHSIZE 8192 /* Bytes */ - #define CODESIZE 128 /* Bytes */ - #define STACKDIFF 320 - #define eAnalogReference ar_aref - #define CPU_RA4M1 - #define SDCARD_SS_PIN 10 - #else #error "Board not supported!" #endif -#if defined(gfxsupport) -const int COLOR_WHITE = 0xffff; -const int COLOR_BLACK = 0; -const int COLOR_GREEN = 0x0600; -const int TEXT_COLOR = COLOR_GREEN; -const int BG_COLOR = COLOR_BLACK; -#endif - - - // C Macros #define nil NULL @@ -520,7 +245,6 @@ FORMAT, }; // Global variables -HardwareSerial *seriell;//pointer to which serial to use according the real board type object Workspace[WORKSPACESIZE] WORDALIGNED MEMBANK; #if defined(CODESIZE) @@ -567,134 +291,88 @@ int modbacktrace (int n) { /* printbacktrace - prints a call backtrace for error messages and break. */ -void -printbacktrace () -{ - if (TraceStart != TraceTop) { - pserial('['); - } - - int tracesize = modbacktrace(TraceTop-TraceStart); - - for (int i=1; i<=tracesize; i++) { - printsymbol(symbol(Backtrace[modbacktrace(TraceTop-i)]), pserial); - if (i!=tracesize) { - pfstring(" <- ", pserial); - } - } - - if (TraceStart != TraceTop) { - pserial(']'); - } +void printbacktrace () { + if (TraceStart != TraceTop) pserial('['); + int tracesize = modbacktrace(TraceTop-TraceStart); + for (int i=1; i<=tracesize; i++) { + printsymbol(symbol(Backtrace[modbacktrace(TraceTop-i)]), pserial); + if (i!=tracesize) pfstring(" <- ", pserial); + } + if (TraceStart != TraceTop) pserial(']'); } /* errorsub - used by all the error routines. - Prints: "Error: 'fname' string", where fname is the name of the - Lisp function in which the error occurred. + Prints: "Error: 'fname' string", where fname is the name of the Lisp function in which the error occurred. */ -void -errorsub(symbol_t fname, const char *string) -{ - pfl(pserial); pfstring("Error", pserial); - - if (TraceStart != TraceTop) { - pserial(' '); - } - - printbacktrace(); - pfstring(": ", pserial); - - if (fname != sym(NIL)) { - pserial('\''); - psymbol(fname, pserial); - pserial('\''); pserial(' '); - } - - pfstring(string, pserial); +void errorsub (symbol_t fname, const char *string) { + pfl(pserial); pfstring("Error", pserial); + if (TraceStart != TraceTop) pserial(' '); + printbacktrace(); + pfstring(": ", pserial); + if (fname != sym(NIL)) { + pserial('\''); + psymbol(fname, pserial); + pserial('\''); pserial(' '); + } + pfstring(string, pserial); } -void -errorend() -{ - GCStack = NULL; - longjmp(*handler, 1); -} +void errorend () { GCStack = NULL; longjmp(*handler, 1); } /* errorsym - prints an error message and reenters the REPL. - Prints: "Error: 'fname' string: symbol", where fname is the name - of the user Lisp function in which the error occurred, - and symbol is the object generating the error. + Prints: "Error: 'fname' string: symbol", where fname is the name of the user Lisp function in which the error occurred, + and symbol is the object generating the error. */ -void -errorsym(symbol_t fname, const char *string, object *symbol) -{ - if (!tstflag(MUFFLEERRORS)) { - errorsub(fname, string); - pserial(':'); - pserial(' '); - printobject(symbol, pserial); - pln(pserial); - } - - errorend(); +void errorsym (symbol_t fname, const char *string, object *symbol) { + if (!tstflag(MUFFLEERRORS)) { + errorsub(fname, string); + pserial(':'); pserial(' '); + printobject(symbol, pserial); + pln(pserial); + } + errorend(); } /* errorsym2 - prints an error message and reenters the REPL. - Prints: "Error: 'fname' string", where fname is the name of the - user Lisp function in which the error occurred. + Prints: "Error: 'fname' string", where fname is the name of the user Lisp function in which the error occurred. */ -void -errorsym2(symbol_t fname, const char *string) -{ - if (!tstflag(MUFFLEERRORS)) { - errorsub(fname, string); - pln(pserial); - } - - errorend(); +void errorsym2 (symbol_t fname, const char *string) { + if (!tstflag(MUFFLEERRORS)) { + errorsub(fname, string); + pln(pserial); + } + errorend(); } /* error - prints an error message and reenters the REPL. - Prints: "Error: 'Context' string: symbol", where Context is the - name of the built-in Lisp function in which the error occurred, - and symbol is the object generating the error. + Prints: "Error: 'Context' string: symbol", where Context is the name of the built-in Lisp function in which the error occurred, + and symbol is the object generating the error. */ -void -error(const char *string, object *symbol) -{ - errorsym(sym(Context), string, symbol); +void error (const char *string, object *symbol) { + errorsym(sym(Context), string, symbol); } /* error2 - prints an error message and reenters the REPL. - Prints: "Error: 'Context' string", where Context is the name of - the built-in Lisp function in which the error occurred. + Prints: "Error: 'Context' string", where Context is the name of the built-in Lisp function in which the error occurred. */ -void -error2(const char *string) -{ - errorsym2(sym(Context), string); +void error2 (const char *string) { + errorsym2(sym(Context), string); } /* formaterr - displays a format error with a ^ pointing to the error */ -void -formaterr(object *formatstr, const char *string, uint8_t p) -{ - pln(pserial); - indent(4, ' ', pserial); - printstring(formatstr, pserial); - pln(pserial); - - indent(p+5, ' ', pserial); pserial('^'); - error2(string); - pln(pserial); - errorend(); +void formaterr (object *formatstr, const char *string, uint8_t p) { + pln(pserial); indent(4, ' ', pserial); printstring(formatstr, pserial); pln(pserial); + indent(p+5, ' ', pserial); pserial('^'); + error2(string); + pln(pserial); + errorend(); } // Save space as these are used multiple times @@ -722,55 +400,42 @@ const char canttakecar[] = "can't take car"; const char canttakecdr[] = "can't take cdr"; const char unknownstreamtype[] = "unknown stream type"; - // Set up workspace /* initworkspace - initialises the workspace into a linked list of free objects */ -void -initworkspace() -{ - Freelist = NULL; - - for (int i=WORKSPACESIZE-1; i>=0; i--) { - object *obj = &Workspace[i]; - car(obj) = NULL; - cdr(obj) = Freelist; - Freelist = obj; - Freespace++; - } +void initworkspace () { + Freelist = NULL; + for (int i=WORKSPACESIZE-1; i>=0; i--) { + object *obj = &Workspace[i]; + car(obj) = NULL; + cdr(obj) = Freelist; + Freelist = obj; + Freespace++; + } } /* myalloc - returns the first object from the linked list of free objects */ -object * -myalloc() -{ - if (Freespace == 0) { - Context = NIL; - error2("no room"); - } - - object *temp = Freelist; - Freelist = cdr(Freelist); - Freespace--; - - return temp; +object *myalloc () { + if (Freespace == 0) { Context = NIL; error2("no room"); } + object *temp = Freelist; + Freelist = cdr(Freelist); + Freespace--; + return temp; } /* myfree - adds obj to the linked list of free objects. inline makes gc significantly faster */ -inline void -myfree(object *obj) -{ - car(obj) = NULL; - cdr(obj) = Freelist; - Freelist = obj; - Freespace++; +inline void myfree (object *obj) { + car(obj) = NULL; + cdr(obj) = Freelist; + Freelist = obj; + Freespace++; } // Make each type of object @@ -778,191 +443,138 @@ myfree(object *obj) /* number - make an integer object with value n and return it */ -object * -number(int n) -{ - object *ptr = myalloc(); - ptr->type = NUMBER; - ptr->integer = n; - - return ptr; +object *number (int n) { + object *ptr = myalloc(); + ptr->type = NUMBER; + ptr->integer = n; + return ptr; } /* makefloat - make a floating point object with value f and return it */ -object * -makefloat(float f) -{ - object *ptr = myalloc(); - ptr->type = FLOAT; - ptr->single_float = f; - - return ptr; +object *makefloat (float f) { + object *ptr = myalloc(); + ptr->type = FLOAT; + ptr->single_float = f; + return ptr; } /* character - make a character object with value c and return it */ -object * -character(uint8_t c) -{ - object *ptr = myalloc(); - ptr->type = CHARACTER; - ptr->chars = c; - - return ptr; +object *character (uint8_t c) { + object *ptr = myalloc(); + ptr->type = CHARACTER; + ptr->chars = c; + return ptr; } /* cons - make a cons with arg1 and arg2 return it */ -object * -cons(object *arg1, object *arg2) -{ - object *ptr = myalloc(); - ptr->car = arg1; - ptr->cdr = arg2; - - return ptr; +object *cons (object *arg1, object *arg2) { + object *ptr = myalloc(); + ptr->car = arg1; + ptr->cdr = arg2; + return ptr; } /* symbol - make a symbol object with value name and return it */ -object * -symbol(symbol_t name) -{ - object *ptr = myalloc(); - ptr->type = SYMBOL; - ptr->name = name; - - return ptr; +object *symbol (symbol_t name) { + object *ptr = myalloc(); + ptr->type = SYMBOL; + ptr->name = name; + return ptr; } /* bsymbol - make a built-in symbol */ -inline object * -bsymbol(builtin_t name) -{ - return intern(twist(name+BUILTINS)); +inline object *bsymbol (builtin_t name) { + return intern(twist(name+BUILTINS)); } /* codehead - make a code header object with value entry and return it */ -object * -codehead(int entry) -{ - object *ptr = myalloc(); - ptr->type = CODE; - ptr->integer = entry; - - return ptr; +object *codehead (int entry) { + object *ptr = myalloc(); + ptr->type = CODE; + ptr->integer = entry; + return ptr; } /* - intern - unless PSRAM: looks through the workspace for an existing - occurrence of symbol name and returns it, otherwise calls - symbol(name) to create a new symbol. + intern - unless PSRAM: looks through the workspace for an existing occurrence of symbol name and returns it, + otherwise calls symbol(name) to create a new symbol. */ -object * -intern (symbol_t name) -{ -#if !defined(BOARD_HAS_PSRAM) - for (int i=0; itype == SYMBOL && obj->name == name) { - return obj; - } - } -#endif - - return symbol(name); +object *intern (symbol_t name) { + #if !defined(BOARD_HAS_PSRAM) + for (int i=0; itype == SYMBOL && obj->name == name) return obj; + } + #endif + return symbol(name); } /* eqsymbols - compares the long string/symbol obj with the string in buffer. */ -bool -eqsymbols(object *obj, char *buffer) -{ - int i = 0; - object *arg = cdr(obj); - - while (!(arg == NULL && buffer[i] == 0)) { - if (arg == NULL || buffer[i] == 0) { - return false; - } - - chars_t test = 0; - int shift = 24; - - for (int j=0; j<4; j++, i++) { - if (buffer[i] == 0) break; - test = test | buffer[i]<chars != test) { - return false; - } - - arg = car(arg); - } - - return true; +bool eqsymbols (object *obj, char *buffer) { + object *arg = cdr(obj); + int i = 0; + while (!(arg == NULL && buffer[i] == 0)) { + if (arg == NULL || buffer[i] == 0) return false; + chars_t test = 0; int shift = 24; + for (int j=0; j<4; j++, i++) { + if (buffer[i] == 0) break; + test = test | buffer[i]<chars != test) return false; + arg = car(arg); + } + return true; } /* - internlong - unless PSRAM looks through the workspace for an - existing occurrence of the long symbol in buffer and returns it, - otherwise calls lispstring(buffer) to create a new symbol. + internlong - unless PSRAM looks through the workspace for an existing occurrence of the long symbol in buffer and returns it, + otherwise calls lispstring(buffer) to create a new symbol. */ -object * -internlong (char *buffer) -{ -#if !defined(BOARD_HAS_PSRAM) - for (int i=0; itype == SYMBOL && longsymbolp(obj) && eqsymbols(obj, buffer)) { - return obj; - } - } -#endif - object *obj = lispstring(buffer); - obj->type = SYMBOL; - return obj; +object *internlong (char *buffer) { + #if !defined(BOARD_HAS_PSRAM) + for (int i=0; itype == SYMBOL && longsymbolp(obj) && eqsymbols(obj, buffer)) return obj; + } + #endif + object *obj = lispstring(buffer); + obj->type = SYMBOL; + return obj; } /* - stream - makes a stream object defined by streamtype and address, - and returns it + stream - makes a stream object defined by streamtype and address, and returns it */ -object * -stream(uint8_t streamtype, uint8_t address) -{ - object *ptr = myalloc(); - ptr->type = STREAM; - ptr->integer = streamtype<<8 | address; - - return ptr; +object *stream (uint8_t streamtype, uint8_t address) { + object *ptr = myalloc(); + ptr->type = STREAM; + ptr->integer = streamtype<<8 | address; + return ptr; } /* newstring - makes an empty string object and returns it */ -object * -newstring() -{ - object *ptr = myalloc(); - ptr->type = STRING; - ptr->chars = 0; - - return ptr; +object *newstring () { + object *ptr = myalloc(); + ptr->type = STRING; + ptr->chars = 0; + return ptr; } // Features @@ -978,26 +590,24 @@ const char sdcard[] = ":sd-card"; const char arm[] = ":arm"; const char riscv[] = ":risc-v"; -object * -features() -{ - object *result = NULL; -#if defined(__riscv) - push(internlong((char *)riscv), result); -#else - push(internlong((char *)arm), result); -#endif -#if defined(sdcardsupport) - push(internlong((char *)sdcard), result); -#endif - push(internlong((char *)gfx), result); - push(internlong((char *)wifi), result); - push(internlong((char *)errorhandling), result); - push(internlong((char *)machinecode), result); - push(internlong((char *)doc), result); - push(internlong((char *)arrays), result); - push(internlong((char *)floatingpoint), result); - return result; +object *features () { + object *result = NULL; + #if defined(__riscv) + push(internlong((char *)riscv), result); + #else + push(internlong((char *)arm), result); + #endif + #if defined(sdcardsupport) + push(internlong((char *)sdcard), result); + #endif + push(internlong((char *)gfx), result); + push(internlong((char *)wifi), result); + push(internlong((char *)errorhandling), result); + push(internlong((char *)machinecode), result); + push(internlong((char *)doc), result); + push(internlong((char *)arrays), result); + push(internlong((char *)floatingpoint), result); + return result; } // Garbage collection @@ -1005,202 +615,142 @@ features() /* markobject - recursively marks reachable objects, starting from obj */ -void -markobject(object *obj) -{ -MARK: - if (obj == NULL) return; - if (marked(obj)) return; +void markobject (object *obj) { + MARK: + if (obj == NULL) return; + if (marked(obj)) return; - object* arg = car(obj); - unsigned int type = obj->type; - mark(obj); + object* arg = car(obj); + unsigned int type = obj->type; + mark(obj); - if (type >= PAIR || type == ZZERO) { // cons - markobject(arg); - obj = cdr(obj); + if (type >= PAIR || type == ZZERO) { // cons + markobject(arg); + obj = cdr(obj); + goto MARK; + } - goto MARK; - } + if (type == ARRAY) { + obj = cdr(obj); + goto MARK; + } - if (type == ARRAY) { - obj = cdr(obj); - - goto MARK; - } - - if ((type == STRING) || (type == SYMBOL && longsymbolp(obj))) { - obj = cdr(obj); - - while (obj != NULL) { - arg = car(obj); - mark(obj); - obj = arg; - } - } + if ((type == STRING) || (type == SYMBOL && longsymbolp(obj))) { + obj = cdr(obj); + while (obj != NULL) { + arg = car(obj); + mark(obj); + obj = arg; + } + } } /* - sweep - goes through the workspace freeing objects that have not - been marked, and unmarks marked objects + sweep - goes through the workspace freeing objects that have not been marked, + and unmarks marked objects */ -void -sweep() -{ - Freelist = NULL; - Freespace = 0; - - for (int i=WORKSPACESIZE-1; i>=0; i--) { - object *obj = &Workspace[i]; - if (!marked(obj)) { - myfree(obj); - } else { - unmark(obj); - } - } +void sweep () { + Freelist = NULL; + Freespace = 0; + for (int i=WORKSPACESIZE-1; i>=0; i--) { + object *obj = &Workspace[i]; + if (!marked(obj)) myfree(obj); else unmark(obj); + } } /* - gc - performs garbage collection by calling markobject() on each - of the pointers to objects in use, followed by sweep() to free - unused objects. + gc - performs garbage collection by calling markobject() on each of the pointers to objects in use, + followed by sweep() to free unused objects. */ -void -gc(object *form, object *env) -{ -#if defined(printgcs) - int start = Freespace; -#endif - - markobject(tee); - markobject(GlobalEnv); - markobject(GCStack); - markobject(form); - markobject(env); - sweep(); - -#if defined(printgcs) - pfl(pserial); - pserial('{'); - pint(Freespace - start, pserial); - pserial('}'); -#endif +void gc (object *form, object *env) { + #if defined(printgcs) + int start = Freespace; + #endif + markobject(tee); + markobject(GlobalEnv); + markobject(GCStack); + markobject(form); + markobject(env); + sweep(); + #if defined(printgcs) + pfl(pserial); pserial('{'); pint(Freespace - start, pserial); pserial('}'); + #endif } // Compact image /* - movepointer - Corrects pointers to an object that has been moved - from 'from' to 'to'. Only need to scan addresses below 'from' - as there are no accessible objects above that. + movepointer - Corrects pointers to an object that has been moved from 'from' to 'to'. + Only need to scan addresses below 'from' as there are no accessible objects above that. */ -void -movepointer(object *from, object *to) -{ - uintptr_t limit = ((uintptr_t)(from) - (uintptr_t)(Workspace))/sizeof(uintptr_t); - for (uintptr_t i=0; itype) & ~MARKBIT; - if (marked(obj) && (type >= ARRAY || type==ZZERO || \ - (type == SYMBOL && longsymbolp(obj)))) { - if (car(obj) == (object *)((uintptr_t)from | MARKBIT)) { - car(obj) = (object *)((uintptr_t)to | MARKBIT); - } - - if (cdr(obj) == from) { - cdr(obj) = to; - } - } - } - - // Fix strings and long symbols for (uintptr_t i=0; itype) & ~MARKBIT; - if (type == STRING || (type == SYMBOL && longsymbolp(obj))) { - obj = cdr(obj); - while (obj != NULL) { - if (cdr(obj) == to) { - cdr(obj) = from; - } - - obj = (object *)((uintptr_t)(car(obj)) & ~MARKBIT); - } - } - } - } +void movepointer (object *from, object *to) { + uintptr_t limit = ((uintptr_t)(from) - (uintptr_t)(Workspace))/sizeof(uintptr_t); + for (uintptr_t i=0; itype) & ~MARKBIT; + if (marked(obj) && (type >= ARRAY || type==ZZERO || (type == SYMBOL && longsymbolp(obj)))) { + if (car(obj) == (object *)((uintptr_t)from | MARKBIT)) + car(obj) = (object *)((uintptr_t)to | MARKBIT); + if (cdr(obj) == from) cdr(obj) = to; + } + } + // Fix strings and long symbols + for (uintptr_t i=0; itype) & ~MARKBIT; + if (type == STRING || (type == SYMBOL && longsymbolp(obj))) { + obj = cdr(obj); + while (obj != NULL) { + if (cdr(obj) == to) cdr(obj) = from; + obj = (object *)((uintptr_t)(car(obj)) & ~MARKBIT); + } + } + } + } } /* - compactimage - Marks all accessible objects. Moves the last marked - object down to the first free space gap, correcting pointers by - calling movepointer(). Then repeats until there are no more gaps. + compactimage - Marks all accessible objects. Moves the last marked object down to the first free space gap, correcting + pointers by calling movepointer(). Then repeats until there are no more gaps. */ -uintptr_t -compactimage(object **arg) -{ - markobject(tee); - markobject(GlobalEnv); - markobject(GCStack); - object *firstfree = Workspace; - - while (marked(firstfree)) { - firstfree++; - } - - object *obj = &Workspace[WORKSPACESIZE-1]; - - while (firstfree < obj) { - if (marked(obj)) { - car(firstfree) = car(obj); - cdr(firstfree) = cdr(obj); - unmark(obj); - movepointer(obj, firstfree); - - if (GlobalEnv == obj) { - GlobalEnv = firstfree; - } - - if (GCStack == obj) { - GCStack = firstfree; - } - - if (*arg == obj) { - *arg = firstfree; - } - - while (marked(firstfree)) { - firstfree++; - } - } - obj--; - } - - sweep(); - return firstfree - Workspace; +uintptr_t compactimage (object **arg) { + markobject(tee); + markobject(GlobalEnv); + markobject(GCStack); + object *firstfree = Workspace; + while (marked(firstfree)) firstfree++; + object *obj = &Workspace[WORKSPACESIZE-1]; + while (firstfree < obj) { + if (marked(obj)) { + car(firstfree) = car(obj); + cdr(firstfree) = cdr(obj); + unmark(obj); + movepointer(obj, firstfree); + if (GlobalEnv == obj) GlobalEnv = firstfree; + if (GCStack == obj) GCStack = firstfree; + if (*arg == obj) *arg = firstfree; + while (marked(firstfree)) firstfree++; + } + obj--; + } + sweep(); + return firstfree - Workspace; } // Make SD card filename -char * -MakeFilename(object *arg, char *buffer) -{ - int max = BUFFERSIZE-1; - buffer[0]='/'; - int i = 1; - - do { - char c = nthchar(arg, i-1); - if (c == '\0') { - break; - } - - buffer[i++] = c; - } while (i>8 & 0xFF); - file.write(data>>16 & 0xFF); - file.write(data>>24 & 0xFF); +void SDWrite32 (File file, int data) { + file.write(data & 0xFF); file.write(data>>8 & 0xFF); + file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF); } -int -SDRead32(File file) -{ - uintptr_t b0 = file.read(); - uintptr_t b1 = file.read(); - uintptr_t b2 = file.read(); - uintptr_t b3 = file.read(); - - return b0 | b1<<8 | b2<<16 | b3<<24; +int SDRead32 (File file) { + uintptr_t b0 = file.read(); uintptr_t b1 = file.read(); + uintptr_t b2 = file.read(); uintptr_t b3 = file.read(); + return b0 | b1<<8 | b2<<16 | b3<<24; } - #elif defined(LITTLEFS) -void -FSWrite32(File file, uint32_t data) -{ - union { - uint32_t data2; - uint8_t u8[4]; - }; - - data2 = data; - if (file.write(u8, 4) != 4) { - error2("not enough room"); - } +void FSWrite32 (File file, uint32_t data) { + union { uint32_t data2; uint8_t u8[4]; }; + data2 = data; + if (file.write(u8, 4) != 4) error2("not enough room"); } -uint32_t -FSRead32(File file) -{ - union { - uint32_t data; - uint8_t u8[4]; - }; - - file.read(u8, 4); - return data; +uint32_t FSRead32 (File file) { + union { uint32_t data; uint8_t u8[4]; }; + file.read(u8, 4); + return data; } - #elif defined(DATAFLASH) // Winbond DataFlash support for Adafruit M4 Express boards #define PAGEPROG 0x02 @@ -1283,652 +802,402 @@ const int sck = 38, ssel = 39, mosi = 37, miso = 36; const int sck = PIN_QSPI_SCK, ssel = PIN_QSPI_CS, mosi = PIN_QSPI_IO0, miso = PIN_QSPI_IO1; #endif -void -FlashBusy() -{ - digitalWrite(ssel, 0); - FlashWrite(READSTATUS); - - while ((FlashReadByte() & 1) != 0); - - digitalWrite(ssel, 1); +void FlashBusy () { + digitalWrite(ssel, 0); + FlashWrite(READSTATUS); + while ((FlashReadByte() & 1) != 0); + digitalWrite(ssel, 1); } -inline void -FlashWrite(uint8_t data) -{ - shiftOut(mosi, sck, MSBFIRST, data); +inline void FlashWrite (uint8_t data) { + shiftOut(mosi, sck, MSBFIRST, data); } -inline uint8_t -FlashReadByte() -{ - return shiftIn(miso, sck, MSBFIRST); +inline uint8_t FlashReadByte () { + return shiftIn(miso, sck, MSBFIRST); } -void -FlashWriteByte(uint32_t *addr, uint8_t data) -{ - // New page - if (((*addr) & 0xFF) == 0) { - digitalWrite(ssel, 1); - FlashBusy(); - FlashWriteEnable(); - digitalWrite(ssel, 0); - FlashWrite(PAGEPROG); - FlashWrite((*addr)>>16); - FlashWrite((*addr)>>8); - FlashWrite(0); - } - - FlashWrite(data); - (*addr)++; +void FlashWriteByte (uint32_t *addr, uint8_t data) { + // New page + if (((*addr) & 0xFF) == 0) { + digitalWrite(ssel, 1); + FlashBusy(); + FlashWriteEnable(); + digitalWrite(ssel, 0); + FlashWrite(PAGEPROG); + FlashWrite((*addr)>>16); + FlashWrite((*addr)>>8); + FlashWrite(0); + } + FlashWrite(data); + (*addr)++; } -void -FlashWriteEnable() -{ - digitalWrite(ssel, 0); - FlashWrite(WRITEENABLE); - digitalWrite(ssel, 1); +void FlashWriteEnable () { + digitalWrite(ssel, 0); + FlashWrite(WRITEENABLE); + digitalWrite(ssel, 1); } -bool -FlashCheck() -{ - uint8_t devID; - - digitalWrite(ssel, HIGH); pinMode(ssel, OUTPUT); - pinMode(sck, OUTPUT); - pinMode(mosi, OUTPUT); - pinMode(miso, INPUT); - digitalWrite(sck, LOW); digitalWrite(mosi, HIGH); - digitalWrite(ssel, LOW); - FlashWrite(READID); - - for (uint8_t i=0; i<4; i++) { - FlashReadByte(); - } - - devID = FlashReadByte(); - digitalWrite(ssel, HIGH); - - return (devID >= 0x14 && devID <= 0x17); // true = found correct device +bool FlashCheck () { + uint8_t devID; + digitalWrite(ssel, HIGH); pinMode(ssel, OUTPUT); + pinMode(sck, OUTPUT); + pinMode(mosi, OUTPUT); + pinMode(miso, INPUT); + digitalWrite(sck, LOW); digitalWrite(mosi, HIGH); + digitalWrite(ssel, LOW); + FlashWrite(READID); + for (uint8_t i=0; i<4; i++) FlashReadByte(); + devID = FlashReadByte(); + digitalWrite(ssel, HIGH); + return (devID >= 0x14 && devID <= 0x17); // true = found correct device } -void -FlashBeginWrite(uint32_t *addr, uint32_t bytes) -{ - *addr = 0; - uint8_t blocks = (bytes+65535)/65536; - - // Erase 64K - for (uint8_t b=0; b>8 & 0xFF); - FlashWriteByte(addr, data>>16 & 0xFF); - FlashWriteByte(addr, data>>24 & 0xFF); +void FlashWrite32 (uint32_t *addr, uint32_t data) { + FlashWriteByte(addr, data & 0xFF); FlashWriteByte(addr, data>>8 & 0xFF); + FlashWriteByte(addr, data>>16 & 0xFF); FlashWriteByte(addr, data>>24 & 0xFF); } -inline void -FlashEndWrite (uint32_t *addr) -{ - (void) addr; - digitalWrite(ssel, 1); - FlashBusy(); +inline void FlashEndWrite (uint32_t *addr) { + (void) addr; + digitalWrite(ssel, 1); + FlashBusy(); } -void -FlashBeginRead(uint32_t *addr) -{ - *addr = 0; - FlashBusy(); - digitalWrite(ssel, 0); - FlashWrite(READDATA); - FlashWrite(0); - FlashWrite(0); - FlashWrite(0); +void FlashBeginRead (uint32_t *addr) { + *addr = 0; + FlashBusy(); + digitalWrite(ssel, 0); + FlashWrite(READDATA); + FlashWrite(0); FlashWrite(0); FlashWrite(0); } -uint32_t -FlashRead32(uint32_t *addr) -{ - (void) addr; - uint8_t b0 = FlashReadByte(); - uint8_t b1 = FlashReadByte(); - uint8_t b2 = FlashReadByte(); - uint8_t b3 = FlashReadByte(); - - return b0 | b1<<8 | b2<<16 | b3<<24; +uint32_t FlashRead32 (uint32_t *addr) { + (void) addr; + uint8_t b0 = FlashReadByte(); uint8_t b1 = FlashReadByte(); + uint8_t b2 = FlashReadByte(); uint8_t b3 = FlashReadByte(); + return b0 | b1<<8 | b2<<16 | b3<<24; } -inline void -FlashEndRead(uint32_t *addr) -{ - (void) addr; - digitalWrite(ssel, 1); +inline void FlashEndRead(uint32_t *addr) { + (void) addr; + digitalWrite(ssel, 1); } #elif defined(CPUFLASH) // For ATSAMD21 __attribute__((__aligned__(256))) static const uint8_t flash_store[FLASHSIZE] = { }; -void -row_erase(const volatile void *addr) -{ - NVMCTRL->ADDR.reg = ((uint32_t)addr) / 2; - NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; - - while (!NVMCTRL->INTFLAG.bit.READY); +void row_erase (const volatile void *addr) { + NVMCTRL->ADDR.reg = ((uint32_t)addr) / 2; + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; + while (!NVMCTRL->INTFLAG.bit.READY); } -void -page_clear() -{ - // Execute "PBC" Page Buffer Clear - NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC; - while (NVMCTRL->INTFLAG.bit.READY == 0); +void page_clear () { + // Execute "PBC" Page Buffer Clear + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC; + while (NVMCTRL->INTFLAG.bit.READY == 0); } -void -page_write() -{ - NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP; - while (NVMCTRL->INTFLAG.bit.READY == 0); +void page_write () { + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP; + while (NVMCTRL->INTFLAG.bit.READY == 0); } -bool -FlashCheck() -{ - return true; +bool FlashCheck() { + return true; } -void -FlashBeginWrite(uint32_t *addr, uint32_t bytes) -{ - (void) bytes; - *addr = (uint32_t)flash_store; - - // Disable automatic page write - NVMCTRL->CTRLB.bit.MANW = 1; +void FlashBeginWrite(uint32_t *addr, uint32_t bytes) { + (void) bytes; + *addr = (uint32_t)flash_store; + // Disable automatic page write + NVMCTRL->CTRLB.bit.MANW = 1; } -void -FlashWrite32(uint32_t *addr, uint32_t data) -{ - if (((*addr) & 0xFF) == 0) { - row_erase((const volatile void *)(*addr)); - } - - if (((*addr) & 0x3F) == 0) { - page_clear(); - } - - *(volatile uint32_t *)(*addr) = data; - (*addr) = (*addr) + 4; - - if (((*addr) & 0x3F) == 0) { - page_write(); - } +void FlashWrite32 (uint32_t *addr, uint32_t data) { + if (((*addr) & 0xFF) == 0) row_erase((const volatile void *)(*addr)); + if (((*addr) & 0x3F) == 0) page_clear(); + *(volatile uint32_t *)(*addr) = data; + (*addr) = (*addr) + 4; + if (((*addr) & 0x3F) == 0) page_write(); } -void -FlashEndWrite(uint32_t *addr) -{ - if (((*addr) & 0x3F) != 0) { - page_write(); - } +void FlashEndWrite (uint32_t *addr) { + if (((*addr) & 0x3F) != 0) page_write(); } -void -FlashBeginRead(uint32_t *addr) -{ - *addr = (uint32_t)flash_store; +void FlashBeginRead(uint32_t *addr) { + *addr = (uint32_t)flash_store; } -uint32_t -FlashRead32(uint32_t *addr) -{ - uint32_t data = *(volatile const uint32_t *)(*addr); - (*addr) = (*addr) + 4; - - return data; +uint32_t FlashRead32 (uint32_t *addr) { + uint32_t data = *(volatile const uint32_t *)(*addr); + (*addr) = (*addr) + 4; + return data; } -void -FlashEndRead(uint32_t *addr) -{ - (void) addr; +void FlashEndRead (uint32_t *addr) { + (void) addr; } - #elif defined(EEPROMFLASH) -bool -FlashCheck() -{ - return (EEPROM.length() == FLASHSIZE); + +bool FlashCheck() { + return (EEPROM.length() == FLASHSIZE); } -void -FlashBeginWrite(uint32_t *addr, uint32_t bytes) -{ - (void) bytes; - *addr = 0; +void FlashBeginWrite(uint32_t *addr, uint32_t bytes) { + (void) bytes; + *addr = 0; } -void -FlashWrite32(uint32_t *addr, uint32_t data) -{ - EEPROM.put(*addr, data); - (*addr) = (*addr) + 4; +void FlashWrite32 (uint32_t *addr, uint32_t data) { + EEPROM.put(*addr, data); + (*addr) = (*addr) + 4; } -void -FlashEndWrite(uint32_t *addr) -{ - (void) addr; +void FlashEndWrite (uint32_t *addr) { + (void) addr; } -void -FlashBeginRead(uint32_t *addr) -{ - *addr = 0; +void FlashBeginRead(uint32_t *addr) { + *addr = 0; } -uint32_t -FlashRead32(uint32_t *addr) -{ - uint32_t data; - EEPROM.get(*addr, data); - (*addr) = (*addr) + 4; - - return data; +uint32_t FlashRead32 (uint32_t *addr) { + uint32_t data; + EEPROM.get(*addr, data); + (*addr) = (*addr) + 4; + return data; } -void -FlashEndRead(uint32_t *addr) -{ - (void) addr; +void FlashEndRead (uint32_t *addr) { + (void) addr; } #endif /* - saveimage - saves an image of the workspace to the persistent - storage selected for the platform. + saveimage - saves an image of the workspace to the persistent storage selected for the platform. */ -int -saveimage(object *arg) -{ +int saveimage (object *arg) { #if defined(sdcardsupport) - unsigned int imagesize = compactimage(&arg); -#if defined(RASPBERRY_PI_PICO_PLATFORM) -#if defined(PLATFORM_PICOCALC) - if(!SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI)){ - error2(PSTR("failed to init SD card")); - - return 0; - } -#else - SD.begin(SDCARD_SS_PIN,(uint32_t) SPI_HALF_SPEED, SPI1); -#endif -#else - SDBegin(); -#endif - - File file; - - if (stringp(arg)) { - char buffer[BUFFERSIZE]; - - file = SD.open(MakeFilename(arg, buffer), O_RDWR | O_CREAT | O_TRUNC); - if (!file) { - error2("problem saving to SD card or invalid filename"); - } - - arg = NULL; - } else if (arg == NULL || listp(arg)) { - file = SD.open("/ULISP.IMG", O_RDWR | O_CREAT | O_TRUNC); - if (!file) { - error2("problem saving to SD card"); - } - } else { - error(invalidarg, arg); - } - - SDWrite32(file, (uintptr_t)arg); - SDWrite32(file, imagesize); - SDWrite32(file, (uintptr_t)GlobalEnv); - SDWrite32(file, (uintptr_t)GCStack); - - for (int i=0; i FLASHSIZE) { - error("image too large", number(imagesize)); - } - - uint32_t addr; - FlashBeginWrite(&addr, bytesneeded); - FlashWrite32(&addr, (uintptr_t)arg); - FlashWrite32(&addr, imagesize); - FlashWrite32(&addr, (uintptr_t)GlobalEnv); - FlashWrite32(&addr, (uintptr_t)GCStack); - - for (int i=0; i FLASHSIZE) error("image too large", number(imagesize)); + uint32_t addr; + FlashBeginWrite(&addr, bytesneeded); + FlashWrite32(&addr, (uintptr_t)arg); + FlashWrite32(&addr, imagesize); + FlashWrite32(&addr, (uintptr_t)GlobalEnv); + FlashWrite32(&addr, (uintptr_t)GCStack); + for (int i=0; itype; - return type >= PAIR || type == ZZERO; +bool consp (object *x) { + if (x == NULL) return false; + unsigned int type = x->type; + return type >= PAIR || type == ZZERO; } /* @@ -2019,15 +1259,10 @@ consp(object *x) /* listp - implements Lisp listp */ -bool -listp(object *x) -{ - if (x == NULL) { - return true; - } - - unsigned int type = x->type; - return type >= PAIR || type == ZZERO; +bool listp (object *x) { + if (x == NULL) return true; + unsigned int type = x->type; + return type >= PAIR || type == ZZERO; } /* @@ -2035,10 +1270,8 @@ listp(object *x) */ #define improperp(x) (!listp(x)) -object * -quote(object *arg) -{ - return cons(bsymbol(QUOTE), cons(arg,NULL)); +object *quote (object *arg) { + return cons(bsymbol(QUOTE), cons(arg,NULL)); } // Radix 40 encoding @@ -2046,292 +1279,158 @@ quote(object *arg) /* builtin - converts a symbol name to builtin */ -builtin_t -builtin(symbol_t name) -{ - return (builtin_t)(untwist(name) - BUILTINS); +builtin_t builtin (symbol_t name) { + return (builtin_t)(untwist(name) - BUILTINS); } /* sym - converts a builtin to a symbol name */ -symbol_t -sym (builtin_t x) -{ - return twist(x + BUILTINS); +symbol_t sym (builtin_t x) { + return twist(x + BUILTINS); } /* toradix40 - returns a number from 0 to 39 if the character can be encoded, or -1 otherwise. */ -int8_t -toradix40(char ch) -{ - if (ch == 0) { - return 0; - } - - if (ch >= '0' && ch <= '9') { - return ch-'0'+1; - } - - if (ch == '-') { - return 37; - } - - if (ch == '*') { - return 38; - } - - if (ch == '$') { - return 39; - } - - ch = ch | 0x20; - if (ch >= 'a' && ch <= 'z') { - return ch-'a'+11; - } - - return -1; // Invalid +int8_t toradix40 (char ch) { + if (ch == 0) return 0; + if (ch >= '0' && ch <= '9') return ch-'0'+1; + if (ch == '-') return 37; if (ch == '*') return 38; if (ch == '$') return 39; + ch = ch | 0x20; + if (ch >= 'a' && ch <= 'z') return ch-'a'+11; + return -1; // Invalid } /* fromradix40 - returns the character encoded by the number n. */ -char -fromradix40(char n) -{ - if (n >= 1 && n <= 10) { - return '0'+n-1; - } - - if (n >= 11 && n <= 36) { - return 'a'+n-11; - } - - if (n == 37) { - return '-'; - } - - if (n == 38) { - return '*'; - } - - if (n == 39) { - return '$'; - } - - return 0; +char fromradix40 (char n) { + if (n >= 1 && n <= 10) return '0'+n-1; + if (n >= 11 && n <= 36) return 'a'+n-11; + if (n == 37) return '-'; if (n == 38) return '*'; if (n == 39) return '$'; + return 0; } /* - pack40 - packs six radix40-encoded characters from buffer into a - 32-bit number and returns it. + pack40 - packs six radix40-encoded characters from buffer into a 32-bit number and returns it. */ -uint32_t -pack40(char *buffer) -{ - int x = 0, j = 0; - for (int i=0; i<6; i++) { - x = x * 40 + toradix40(buffer[j]); - if (buffer[j] != 0) { - j++; - } - } - - return x; +uint32_t pack40 (char *buffer) { + int x = 0, j = 0; + for (int i=0; i<6; i++) { + x = x * 40 + toradix40(buffer[j]); + if (buffer[j] != 0) j++; + } + return x; } /* - valid40 - returns true if the symbol in buffer can be encoded as - six radix40-encoded characters. + valid40 - returns true if the symbol in buffer can be encoded as six radix40-encoded characters. */ -bool -valid40(char *buffer) -{ - int t = 11; - - for (int i=0; i<6; i++) { - if (toradix40(buffer[i]) < t) { - return false; - } - - if (buffer[i] == 0) { - break; - } - - t = 0; - } - - return true; +bool valid40 (char *buffer) { + int t = 11; + for (int i=0; i<6; i++) { + if (toradix40(buffer[i]) < t) return false; + if (buffer[i] == 0) break; + t = 0; + } + return true; } /* - digitvalue - returns the numerical value of a hexadecimal digit, - or 16 if invalid. + digitvalue - returns the numerical value of a hexadecimal digit, or 16 if invalid. */ -int8_t -digitvalue(char d) -{ - if (d>='0' && d<='9') { - return d-'0'; - } - - d = d | 0x20; - if (d>='a' && d<='f') { - return d-'a'+10; - } - - return 16; +int8_t digitvalue (char d) { + if (d>='0' && d<='9') return d-'0'; + d = d | 0x20; + if (d>='a' && d<='f') return d-'a'+10; + return 16; } /* checkinteger - check that obj is an integer and return it */ -int -checkinteger(object *obj) -{ - if (!integerp(obj)) { - error(notaninteger, obj); - } - - return obj->integer; +int checkinteger (object *obj) { + if (!integerp(obj)) error(notaninteger, obj); + return obj->integer; } /* - checkbitvalue - check that obj is an integer equal to 0 or 1 and - return it + checkbitvalue - check that obj is an integer equal to 0 or 1 and return it */ -int -checkbitvalue(object *obj) -{ - if (!integerp(obj)) { - error(notaninteger, obj); - } - - int n = obj->integer; - if (n & ~1) { - error("argument is not a bit value", obj); - } - - return n; +int checkbitvalue (object *obj) { + if (!integerp(obj)) error(notaninteger, obj); + int n = obj->integer; + if (n & ~1) error("argument is not a bit value", obj); + return n; } /* - checkintfloat - check that obj is an integer or floating-point - number and return the number + checkintfloat - check that obj is an integer or floating-point number and return the number */ -float -checkintfloat(object *obj) -{ - if (integerp(obj)) { - return (float)obj->integer; - } - - if (!floatp(obj)) { - error(notanumber, obj); - } - - return obj->single_float; +float checkintfloat (object *obj) { + if (integerp(obj)) return (float)obj->integer; + if (!floatp(obj)) error(notanumber, obj); + return obj->single_float; } /* - checkchar - check that obj is a character and return the character + checkchar - check that obj is a character and return the character */ -int -checkchar(object *obj) -{ - if (!characterp(obj)) { - error("argument is not a character", obj); - } - - return obj->chars; +int checkchar (object *obj) { + if (!characterp(obj)) error("argument is not a character", obj); + return obj->chars; } /* checkstring - check that obj is a string */ -object * -checkstring(object *obj) -{ - if (!stringp(obj)) { - error(notastring, obj); - } - - return obj; +object *checkstring (object *obj) { + if (!stringp(obj)) error(notastring, obj); + return obj; } -int -isstream(object *obj) -{ - if (!streamp(obj)) { - error("not a stream", obj); - } - - return obj->integer; +int isstream (object *obj){ + if (!streamp(obj)) error("not a stream", obj); + return obj->integer; } -int -isbuiltin(object *obj, builtin_t n) -{ - return symbolp(obj) && obj->name == sym(n); +int isbuiltin (object *obj, builtin_t n) { + return symbolp(obj) && obj->name == sym(n); } -bool -builtinp(symbol_t name) -{ - return (untwist(name) >= BUILTINS); +bool builtinp (symbol_t name) { + return (untwist(name) >= BUILTINS); } -int -checkkeyword(object *obj) -{ - if (!keywordp(obj)) { - error("argument is not a keyword", obj); - } - - builtin_t kname = builtin(obj->name); - uint8_t context = getminmax(kname); - if (context != 0 && context != Context) { - error(invalidkey, obj); - } - - return ((int)lookupfn(kname)); +int checkkeyword (object *obj) { + if (!keywordp(obj)) error("argument is not a keyword", obj); + builtin_t kname = builtin(obj->name); + uint8_t context = getminmax(kname); + if (context != 0 && context != Context) error(invalidkey, obj); + return ((int)lookupfn(kname)); } /* checkargs - checks that the number of objects in the list args is within the range specified in the symbol lookup table */ -void -checkargs(object *args) -{ - int nargs = listlength(args); - - checkminmax(Context, nargs); +void checkargs (object *args) { + int nargs = listlength(args); + checkminmax(Context, nargs); } /* eqlongsymbol - checks whether two long symbols are equal */ -bool -eqlongsymbol(symbol_t sym1, symbol_t sym2) -{ - object *arg1 = (object *)sym1; object *arg2 = (object *)sym2; - - while ((arg1 != NULL) || (arg2 != NULL)) { - if (arg1 == NULL || arg2 == NULL) { - return false; - } - - if (arg1->chars != arg2->chars) { - return false; - } - - arg1 = car(arg1); arg2 = car(arg2); - } - - return true; +bool eqlongsymbol (symbol_t sym1, symbol_t sym2) { + object *arg1 = (object *)sym1; object *arg2 = (object *)sym2; + while ((arg1 != NULL) || (arg2 != NULL)) { + if (arg1 == NULL || arg2 == NULL) return false; + if (arg1->chars != arg2->chars) return false; + arg1 = car(arg1); arg2 = car(arg2); + } + return true; } /* @@ -2738,6 +1837,7 @@ void pslice (object *array, int size, int slice, object *dims, pfun_t pfun, bool (index & (sizeof(int)==4 ? 0x1F : 0x0F)) & 1, pfun); else printobject(*arrayref(array, index, size), pfun); } else { pfun('('); pslice(array, size, index, cdr(dims), pfun, bitp); pfun(')'); } + testescape(); } } @@ -3388,6 +2488,7 @@ object *dobody (object *args, object *env, bool star) { protect(head); object *ptr = head; object *newenv = env; + protect(newenv); while (varlist != NULL) { object *varform = first(varlist); object *var, *init = NULL, *step = NULL; @@ -3402,7 +2503,9 @@ object *dobody (object *args, object *env, bool star) { } } object *pair = cons(var, init); + unprotect(); // newenv push(pair, newenv); + protect(newenv); if (star) env = newenv; object *cell = cons(cons(step, pair), NULL); cdr(ptr) = cell; ptr = cdr(ptr); @@ -3414,9 +2517,11 @@ object *dobody (object *args, object *env, bool star) { while (eval(endtest, env) == NULL) { object *forms = cddr(args); while (forms != NULL) { - object *result = eval(car(forms), env); + object *result = eval(car(forms), env); if (tstflag(RETURNFLAG)) { clrflag(RETURNFLAG); + unprotect(); // newenv + unprotect(); // head return result; } forms = cdr(forms); @@ -3444,35 +2549,27 @@ object *dobody (object *args, object *env, bool star) { count--; } } - unprotect(); + unprotect(); // newenv + unprotect(); // head return eval(tf_progn(results, env), env); } -// I2C interface for up to two ports, using Arduino Wire: in -// picocalc, i2c0 is for keyboard. +// I2C interface for up to two ports, using Arduino Wire + void I2Cinit (TwoWire *port, bool enablePullup) { (void) enablePullup; - #if defined(ULISP_I2C1) port->begin(); - #endif } int I2Cread (TwoWire *port) { - #if defined(ULISP_I2C1) return port->read(); - #else - return 0; - #endif } void I2Cwrite (TwoWire *port, uint8_t data) { - #if defined(ULISP_I2C1) port->write(data); - #endif } bool I2Cstart (TwoWire *port, uint8_t address, uint8_t read) { - #if defined(ULISP_I2C1) int ok = true; if (read == 0) { port->beginTransmission(address); @@ -3481,28 +2578,19 @@ bool I2Cstart (TwoWire *port, uint8_t address, uint8_t read) { } else port->requestFrom(address, I2Ccount); return ok; - #else - return false; - #endif } bool I2Crestart (TwoWire *port, uint8_t address, uint8_t read) { - #if defined(ULISP_I2C1) int error = (port->endTransmission(false) != 0); if (read == 0) port->beginTransmission(address); else port->requestFrom(address, I2Ccount); return error ? false : true; - #else - return false; - #endif } void I2Cstop (TwoWire *port, uint8_t read) { - #if defined(ULISP_I2C1) - if (read == 0) port->endTransmission(); // Check for error? - // Release pins - port->end(); - #endif + if (read == 0) port->endTransmission(); // Check for error? + // Release pins + port->end(); } // Streams @@ -3513,7 +2601,7 @@ void I2Cstop (TwoWire *port, uint8_t read) { || defined(ARDUINO_TEENSY41) || defined(ARDUINO_RASPBERRY_PI_PICO) \ || defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_RASPBERRY_PI_PICO_2) \ || defined(ARDUINO_RASPBERRY_PI_PICO_2W) || defined(ARDUINO_PIMORONI_PICO_PLUS_2) -#define ULISP_SPI1 +#define ULISP_HOWMANYSPI 2 #endif #if defined(ARDUINO_WIO_TERMINAL) || defined(ARDUINO_BBC_MICROBIT_V2) \ || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(MAX32620) \ @@ -3522,17 +2610,16 @@ void I2Cstop (TwoWire *port, uint8_t read) { || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ || defined(ARDUINO_PIMORONI_PICO_PLUS_2) || defined(ARDUINO_GRAND_CENTRAL_M4) \ || defined(ARDUINO_NRF52840_CIRCUITPLAY) -#define ULISP_I2C1 +#define ULISP_HOWMANYI2C 2 #endif #if defined(ARDUINO_SAM_DUE) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) -#define ULISP_SERIAL3 +#define ULISP_HOWMANYSERIAL 4 #elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ || defined(ARDUINO_PIMORONI_PICO_PLUS_2) -#define ULISP_SPI1 -#define ULISP_SERIAL1 +#define ULISP_HOWMANYSERIAL 3 #elif !defined(CPU_NRF51822) && !defined(CPU_NRF52833) && !defined(ARDUINO_FEATHER_F405) -#define ULISP_SERIAL1 +#define ULISP_HOWMANYSERIAL 2 #endif #if defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ || defined(ARDUINO_UNOWIFIR4) @@ -3540,20 +2627,20 @@ void I2Cstop (TwoWire *port, uint8_t read) { #endif inline int spiread () { return SPI.transfer(0); } -#if defined(ULISP_SPI1) +#if ULISP_HOWMANYSPI == 2 inline int spi1read () { return SPI1.transfer(0); } #endif inline int i2cread () { return I2Cread(&Wire); } -#if defined(ULISP_I2C1) +#if ULISP_HOWMANYI2C == 2 inline int i2c1read () { return I2Cread(&Wire1); } #endif -#if defined(ULISP_SERIAL3) +#if ULISP_HOWMANYSERIAL == 4 inline int serial3read () { while (!Serial3.available()) testescape(); return Serial3.read(); } #endif -#if defined(ULISP_SERIAL3) || defined(ULISP_SERIAL2) +#if ULISP_HOWMANYSERIAL == 4 || ULISP_HOWMANYSERIAL == 3 inline int serial2read () { while (!Serial2.available()) testescape(); return Serial2.read(); } #endif -#if defined(ULISP_SERIAL3) || defined(ULISP_SERIAL2) || defined(ULISP_SERIAL1) +#if ULISP_HOWMANYSERIAL == 4 || ULISP_HOWMANYSERIAL == 3 || ULISP_HOWMANYSERIAL == 2 inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } #endif #if defined(sdcardsupport) @@ -3578,26 +2665,21 @@ inline int WiFiread () { LastChar = 0; return temp; } - while (!server.accept()) testescape(); + while (!client.available()) testescape(); return client.read(); } #endif void serialbegin (int address, int baud) { - #if defined(ULISP_SERIAL3) + #if ULISP_HOWMANYSERIAL == 4 if (address == 1) Serial1.begin((long)baud*100); else if (address == 2) Serial2.begin((long)baud*100); else if (address == 3) Serial3.begin((long)baud*100); - #elif defined(ULISP_SERIAL2) + #elif ULISP_HOWMANYSERIAL == 3 if (address == 1) Serial1.begin((long)baud*100); else if (address == 2) Serial2.begin((long)baud*100); - #elif defined(ULISP_SERIAL1) - #if defined(PLATFORM_PICOCALC) - // Waveshare uses Serial1 for default. - if (address == 1) {} - #else - if (address == 1) Serial1.begin((long)baud*100); - #endif + #elif ULISP_HOWMANYSERIAL == 2 + if (address == 1) Serial1.begin((long)baud*100); #else (void) baud; if (false); @@ -3606,20 +2688,15 @@ void serialbegin (int address, int baud) { } void serialend (int address) { - #if defined(ULISP_SERIAL3) + #if ULISP_HOWMANYSERIAL == 4 if (address == 1) {Serial1.flush(); Serial1.end(); } else if (address == 2) {Serial2.flush(); Serial2.end(); } else if (address == 3) {Serial3.flush(); Serial3.end(); } - #elif defined(ULISP_SERIAL2) + #elif ULISP_HOWMANYSERIAL == 3 if (address == 1) {Serial1.flush(); Serial1.end(); } else if (address == 2) {Serial2.flush(); Serial2.end(); } - #elif defined(ULISP_SERIAL1) - #if defined(PLATFORM_PICOCALC) - if (address == 1) {Serial1.flush();} - #else - if (address == 1) {Serial1.flush(); Serial1.end(); } - #endif - + #elif ULISP_HOWMANYSERIAL == 2 + if (address == 1) {Serial1.flush(); Serial1.end(); } #else if (false); #endif @@ -3636,25 +2713,25 @@ gfun_t gstreamfun (object *args) { } if (streamtype == I2CSTREAM) { if (address < 128) gfun = i2cread; - #if defined(ULISP_I2C1) + #if ULISP_HOWMANYI2C == 2 else gfun = i2c1read; #endif } else if (streamtype == SPISTREAM) { if (address < 128) gfun = spiread; - #if defined(ULISP_SPI1) + #if ULISP_HOWMANYSPI == 2 else gfun = spi1read; #endif } else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; - #if defined(ULISP_SERIAL3) + #if ULISP_HOWMANYSERIAL == 4 else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; else if (address == 3) gfun = serial3read; - #elif defined(ULISP_SERIAL2) + #elif ULISP_HOWMANYSERIAL == 3 else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; - #elif defined(ULISP_SERIAL1) + #elif ULISP_HOWMANYSERIAL == 2 else if (address == 1) gfun = serial1read; #endif } @@ -3669,21 +2746,21 @@ gfun_t gstreamfun (object *args) { } inline void spiwrite (char c) { SPI.transfer(c); } -#if defined(ULISP_SPI1) +#if ULISP_HOWMANYSPI == 2 inline void spi1write (char c) { SPI1.transfer(c); } #endif inline void i2cwrite (char c) { I2Cwrite(&Wire, c); } -#if defined(ULISP_I2C1) +#if ULISP_HOWMANYI2C == 2 inline void i2c1write (char c) { I2Cwrite(&Wire1, c); } #endif -#if defined(ULISP_SERIAL3) +#if ULISP_HOWMANYSERIAL == 4 inline void serial1write (char c) { Serial1.write(c); } inline void serial2write (char c) { Serial2.write(c); } inline void serial3write (char c) { Serial3.write(c); } -#elif defined(ULISP_SERIAL2) +#elif ULISP_HOWMANYSERIAL == 3 inline void serial2write (char c) { Serial2.write(c); } inline void serial1write (char c) { Serial1.write(c); } -#elif defined(ULISP_SERIAL1) +#elif ULISP_HOWMANYSERIAL == 2 inline void serial1write (char c) { Serial1.write(c); } #endif #if defined(sdcardsupport) @@ -3706,24 +2783,24 @@ pfun_t pstreamfun (object *args) { } if (streamtype == I2CSTREAM) { if (address < 128) pfun = i2cwrite; - #if defined(ULISP_I2C1) + #if ULISP_HOWMANYI2C == 2 else pfun = i2c1write; #endif } else if (streamtype == SPISTREAM) { if (address < 128) pfun = spiwrite; - #if defined(ULISP_SPI1) + #if ULISP_HOWMANYSPI == 2 else pfun = spi1write; #endif } else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; - #if defined(ULISP_SERIAL3) + #if ULISP_HOWMANYSERIAL == 4 else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; else if (address == 3) pfun = serial3write; - #elif defined(ULISP_SERIAL2) + #elif ULISP_HOWMANYSERIAL == 3 else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; - #elif defined(ULISP_SERIAL1) + #elif ULISP_HOWMANYSERIAL == 2 else if (address == 1) pfun = serial1write; #endif } @@ -3746,226 +2823,74 @@ pfun_t pstreamfun (object *args) { // Check pins - these are board-specific not processor-specific void checkanalogread (int pin) { -#if defined(ARDUINO_SAM_DUE) - if (!(pin>=54 && pin<=65)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SAMD_ZERO) - if (!(pin>=14 && pin<=19)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SAMD_MKRZERO) - if (!(pin>=15 && pin<=21)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_ITSYBITSY_M0) - if (!(pin>=14 && pin<=25)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NEOTRINKEY_M0) - if (!(pin==1 || pin==2 || pin==6)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_GEMMA_M0) - if (!(pin>=8 && pin<=10)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_QTPY_M0) - if (!((pin>=0 && pin<=3) || (pin>=6 && pin<=10))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SEEED_XIAO_M0) - if (!(pin>=0 && pin<=10)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_METRO_M4) - if (!(pin>=14 && pin<=21)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4) - if (!(pin>=14 && pin<=20)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_PYBADGE_M4) - if (!(pin>=14 && pin<=23)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_PYGAMER_M4) - if (!(pin>=14 && pin<=25)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_WIO_TERMINAL) - if (!((pin>=0 && pin<=8))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_GRAND_CENTRAL_M4) - if (!((pin>=67 && pin<=74) || (pin>=54 && pin<=61))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_BBC_MICROBIT) || defined(ARDUINO_SINOBIT) - if (!((pin>=0 && pin<=4) || pin==10)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_BBC_MICROBIT_V2) - if (!((pin>=0 && pin<=4) || pin==10 || pin==29)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_CALLIOPE_MINI) - if (!(pin==1 || pin==2 || (pin>=4 && pin<=6) || pin==21)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_ITSYBITSY) - if (!(pin>=14 && pin<=20)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_Seeed_XIAO_nRF52840) || defined(ARDUINO_Seeed_XIAO_nRF52840_Sense) - if (!(pin>=0 && pin<=5)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_CLUE) - if (!((pin>=0 && pin<=4) || pin==10 || pin==12 || pin==16)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_CIRCUITPLAY) - if (!(pin==0 || (pin>=2 && pin<=3) || pin==6 || (pin>=9 && pin<=10) || (pin>=22 && pin<=23))) error(invalidpin, number(pin)); -#elif defined(MAX32620) - if (!(pin>=49 && pin<=52)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_TEENSY40) - if (!((pin>=14 && pin<=27))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_TEENSY41) - if (!((pin>=14 && pin<=27) || (pin>=38 && pin<=41))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ - || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) \ - || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040) \ +#if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ || defined(ARDUINO_PIMORONI_PICO_PLUS_2) if (!(pin>=26 && pin<=29)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_MINIMA) || defined(ARDUINO_UNOWIFIR4) - if (!((pin>=14 && pin<=21))) error(invalidpin, number(pin)); #endif } void checkanalogwrite (int pin) { -#if defined(ARDUINO_SAM_DUE) - if (!((pin>=2 && pin<=13) || pin==66 || pin==67)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SAMD_ZERO) - if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || pin==14)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SAMD_MKRZERO) - if (!((pin>=0 && pin<=8) || pin==10 || pin==18 || pin==19)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_ITSYBITSY_M0) - if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || (pin>=15 && pin<=16) || (pin>=22 && pin<=25))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NEOTRINKEY_M0) - error2("not supported"); -#elif defined(ARDUINO_GEMMA_M0) - if (!(pin==0 || pin==2 || pin==9 || pin==10)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_QTPY_M0) - if (!(pin==0 || (pin>=2 && pin<=10))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_SEEED_XIAO_M0) - if (!(pin>=0 && pin<=10)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_METRO_M4) - if (!(pin>=0 && pin<=15)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_ITSYBITSY_M4) - if (!(pin==0 || pin==1 || pin==4 || pin==5 || pin==7 || (pin>=9 && pin<=15) || pin==21 || pin==22)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_FEATHER_M4) - if (!(pin==0 || pin==1 || (pin>=4 && pin<=6) || (pin>=9 && pin<=13) || pin==14 || pin==15 || pin==17 || pin==21 || pin==22)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_PYBADGE_M4) - if (!(pin==4 || pin==7 || pin==9 || (pin>=12 && pin<=13) || (pin>=24 && pin<=25) || (pin>=46 && pin<=47))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_PYGAMER_M4) - if (!(pin==4 || pin==7 || pin==9 || (pin>=12 && pin<=13) || (pin>=26 && pin<=27) || (pin>=46 && pin<=47))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_WIO_TERMINAL) - if (!((pin>=0 && pin<=2) || pin==6 || pin==8 || (pin>=12 && pin<=20) || pin==24)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_GRAND_CENTRAL_M4) - if (!((pin>=2 && pin<=9) || pin==11 || (pin>=13 && pin<=45) || pin==48 || (pin>=50 && pin<=53) || pin==58 || pin==61 || pin==68 || pin==69)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_BBC_MICROBIT) || defined(ARDUINO_BBC_MICROBIT_V2) || defined(ARDUINO_SINOBIT) - if (!(pin>=0 && pin<=32)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_CALLIOPE_MINI) - if (!(pin>=0 && pin<=30)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_ITSYBITSY) - if (!(pin>=0 && pin<=25)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_CLUE) - if (!(pin>=0 && pin<=46)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_NRF52840_CIRCUITPLAY) - if (!(pin>=0 && pin<=35)) error(invalidpin, number(pin)); -#elif defined(MAX32620) - if (!((pin>=20 && pin<=29) || pin==32 || (pin>=40 && pin<=48))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_TEENSY40) - if (!((pin>=0 && pin<=15) || (pin>=18 && pin<=19) || (pin>=22 && pin<=25) || (pin>=28 && pin<=29) || (pin>=33 && pin<=39))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_TEENSY41) - if (!((pin>=0 && pin<=15) || (pin>=18 && pin<=19) || (pin>=22 && pin<=25) || (pin>=28 && pin<=29) || pin==33 || (pin>=36 && pin<=37))) error(invalidpin, number(pin)); -#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) \ - || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) \ - || defined(ARDUINO_SEEED_XIAO_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO_2) \ +#if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2) \ || defined(ARDUINO_PIMORONI_PICO_PLUS_2) if (!(pin>=0 && pin<=29)) error(invalidpin, number(pin)); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) if (!((pin>=0 && pin<=29) || pin == 32)) error(invalidpin, number(pin)); -#elif defined(ARDUINO_MINIMA) || defined(ARDUINO_UNOWIFIR4) - if (!((pin>=0 && pin<=21))) error(invalidpin, number(pin)); #endif } // Note +void play_tone (uint freq) { // duty_c between 0..10000 + gpio_set_function(AUDIO_PIN_L, GPIO_FUNC_PWM); + gpio_set_function(AUDIO_PIN_R, GPIO_FUNC_PWM); + uint slice_l = pwm_gpio_to_slice_num(AUDIO_PIN_L); + uint slice_r = pwm_gpio_to_slice_num(AUDIO_PIN_R); + pwm_config config = pwm_get_default_config(); + float div = (float)clock_get_hz(clk_sys) / (freq * 10000); + pwm_config_set_clkdiv(&config, div); + pwm_config_set_wrap(&config, 10000); + pwm_init(slice_l, &config, true); // start the pwm running according to the config + pwm_init(slice_r, &config, true); + pwm_set_gpio_level(AUDIO_PIN_L, 5000); //connect the pin to the pwm engine and set the duty cycle. + pwm_set_gpio_level(AUDIO_PIN_R, 5000); + }; + +void play_tone_off() { + uint slice_l = pwm_gpio_to_slice_num(AUDIO_PIN_L); + uint slice_r = pwm_gpio_to_slice_num(AUDIO_PIN_R); + pwm_config config = pwm_get_default_config(); + pwm_init(slice_l, &config, false); + pwm_init(slice_r, &config, false); +}; + const int scale[] = {4186,4435,4699,4978,5274,5588,5920,6272,6645,7040,7459,7902}; void playnote (int pin, int note, int octave) { -#if defined(ARDUINO_NRF52840_CLUE) || defined(ARDUINO_NRF52840_CIRCUITPLAY) \ - || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ - || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) \ - || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040) \ - || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ - || defined(ARDUINO_PIMORONI_PICO_PLUS_2) || defined(ARDUINO_WIO_TERMINAL) + (void) pin; int oct = octave + note/12; int prescaler = 8 - oct; if (prescaler<0 || prescaler>8) error("octave out of range", number(oct)); - tone(pin, scale[note%12]>>prescaler); -#else - (void) pin, (void) note, (void) octave; -#endif + play_tone(scale[note%12]>>prescaler); } void nonote (int pin) { -#if defined(ARDUINO_NRF52840_CLUE) || defined(ARDUINO_NRF52840_CIRCUITPLAY) \ - || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ - || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) \ - || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040) \ - || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) \ - || defined(ARDUINO_PIMORONI_PICO_PLUS_2) || defined(ARDUINO_WIO_TERMINAL) - noTone(pin); -#else (void) pin; -#endif + play_tone_off(); } // Sleep -#if defined(CPU_ATSAMD21) -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(CPU_ATSAMD21) - // 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 initsleep () { } void doze (int secs) { -#if defined(CPU_ATSAMD21) - 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 + delay(1000 * secs); } // Prettyprint const int PPINDENT = 2; -const int PPWIDTH = 80; +const int PPWIDTH = 52; const int GFXPPWIDTH = 52; // 320 pixel wide screen int ppwidth = PPWIDTH; @@ -4055,6 +2980,7 @@ void superprint (object *form, int lm, pfun_t pfun) { form = cdr(form); } pfun(')'); + testescape(); } } @@ -4598,7 +3524,7 @@ object *sp_withserial (object *args, object *env) { object *var = first(params); int address = checkinteger(eval(second(params), env)); params = cddr(params); - int baud = BAUDRATE; + int baud = 96; if (params != NULL) baud = checkinteger(eval(first(params), env)); object *pair = cons(var, stream(SERIALSTREAM, address)); push(pair,env); @@ -4633,7 +3559,7 @@ object *sp_withi2c (object *args, object *env) { } // Top bit of address is I2C port TwoWire *port = &Wire; - #if defined(ULISP_I2C1) + #if ULISP_HOWMANYI2C == 2 if (address > 127) port = &Wire1; #endif I2Cinit(port, 1); // Pullups @@ -4681,7 +3607,7 @@ object *sp_withspi (object *args, object *env) { object *pair = cons(var, stream(SPISTREAM, pin + 128*address)); push(pair,env); SPIClass *spiClass = &SPI; - #if defined(ULISP_SPI1) + #if ULISP_HOWMANYSPI == 2 if (address == 1) spiClass = &SPI1; #endif spiClass->begin(); @@ -4710,18 +3636,7 @@ object *sp_withsdcard (object *args, object *env) { Context = temp; if (!stringp(filename)) error("filename is not a string", filename); params = cdr(params); - #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) - #if defined(PLATFORM_PICOCALC) - if(!SD.begin(SDCARD_SS_PIN,(uint32_t) SPI_HALF_SPEED, SPI )){ - error2(PSTR("failed to init SD card")); - return nil; - } - #else - SD.begin(SDCARD_SS_PIN,(uint32_t) SPI_HALF_SPEED, SPI1); - #endif - #else - SD.begin(SDCARD_SS_PIN); - #endif + SDBegin(); int mode = 0; if (params != NULL && first(params) != NULL) mode = checkinteger(first(params)); int oflag = O_READ; @@ -6632,14 +5547,12 @@ object *fn_readline (object *args, object *env) { (write-byte number [stream]) Writes a byte to a stream. */ -inline void serialwrite (char c) { Serial.write(c); } - object *fn_writebyte (object *args, object *env) { (void) env; - int value = checkinteger(first(args)); + int c = checkinteger(first(args)); pfun_t pfun = pstreamfun(cdr(args)); - if (pfun == pserial) pfun = serialwrite; - (pfun)(value); + if (c == '\n' && pfun == pserial) Serial.write('\n'); + else (pfun)(c); return nil; } @@ -6695,7 +5608,7 @@ object *fn_restarti2c (object *args, object *env) { if (stream>>8 != I2CSTREAM) error2("not an i2c stream"); TwoWire *port; if (address < 128) port = &Wire; - #if defined(ULISP_I2C1) + #if ULISP_HOWMANYI2C == 2 else port = &Wire1; #endif return I2Crestart(port, address & 0x7F, read) ? tee : nil; @@ -6743,33 +5656,21 @@ object *fn_backtrace (object *args, object *env) { /* (save-image [symbol]) - Saves the current uLisp image to non-volatile memory or SD card - so it can be loaded using load-image. + Saves the current uLisp image to non-volatile memory or SD card so it can be loaded using load-image. */ -object * -fn_saveimage(object *args, object *env) -{ - if (args != NULL) { - args = eval(first(args), env); - } - - return number(saveimage(args)); +object *fn_saveimage (object *args, object *env) { + if (args != NULL) args = eval(first(args), env); + return number(saveimage(args)); } /* (load-image [filename]) Loads a saved uLisp image from non-volatile memory or SD card. */ -object * -fn_loadimage(object *args, object *env) -{ - (void) env; - - if (args != NULL) { - args = first(args); - } - - return number(loadimage(args)); +object *fn_loadimage (object *args, object *env) { + (void) env; + if (args != NULL) args = first(args); + return number(loadimage(args)); } /* @@ -7367,7 +6268,7 @@ object *sp_withclient (object *args, object *env) { params = cdr(params); int n; if (params == NULL) { - client = server.accept(); + client = server.available(); if (!client) return nil; n = 2; } else { @@ -7542,7 +6443,7 @@ object *sp_withgfx (object *args, object *env) { object *fn_drawpixel (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t colour = TEXT_COLOR; + uint16_t colour = COLOR_WHITE; if (cddr(args) != NULL) colour = checkinteger(third(args)); tft.drawPixel(checkinteger(first(args)), checkinteger(second(args)), colour); #else @@ -7558,7 +6459,7 @@ object *fn_drawpixel (object *args, object *env) { object *fn_drawline (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[4], colour = TEXT_COLOR; + uint16_t params[4], colour = COLOR_WHITE; for (int i=0; i<4; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.drawLine(params[0], params[1], params[2], params[3], colour); @@ -7576,7 +6477,7 @@ object *fn_drawline (object *args, object *env) { object *fn_drawrect (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[4], colour = TEXT_COLOR; + uint16_t params[4], colour = COLOR_WHITE; for (int i=0; i<4; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.drawRect(params[0], params[1], params[2], params[3], colour); @@ -7594,7 +6495,7 @@ object *fn_drawrect (object *args, object *env) { object *fn_fillrect (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[4], colour = TEXT_COLOR; + uint16_t params[4], colour = COLOR_WHITE; for (int i=0; i<4; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.fillRect(params[0], params[1], params[2], params[3], colour); @@ -7612,7 +6513,7 @@ object *fn_fillrect (object *args, object *env) { object *fn_drawcircle (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[3], colour = TEXT_COLOR; + uint16_t params[3], colour = COLOR_WHITE; for (int i=0; i<3; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.drawCircle(params[0], params[1], params[2], colour); @@ -7630,7 +6531,7 @@ object *fn_drawcircle (object *args, object *env) { object *fn_fillcircle (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[3], colour = TEXT_COLOR; + uint16_t params[3], colour = COLOR_WHITE; for (int i=0; i<3; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.fillCircle(params[0], params[1], params[2], colour); @@ -7648,7 +6549,7 @@ object *fn_fillcircle (object *args, object *env) { object *fn_drawroundrect (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[5], colour = TEXT_COLOR; + uint16_t params[5], colour = COLOR_WHITE; for (int i=0; i<5; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.drawRoundRect(params[0], params[1], params[2], params[3], params[4], colour); @@ -7666,7 +6567,7 @@ object *fn_drawroundrect (object *args, object *env) { object *fn_fillroundrect (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[5], colour = TEXT_COLOR; + uint16_t params[5], colour = COLOR_WHITE; for (int i=0; i<5; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.fillRoundRect(params[0], params[1], params[2], params[3], params[4], colour); @@ -7684,7 +6585,7 @@ object *fn_fillroundrect (object *args, object *env) { object *fn_drawtriangle (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[6], colour = TEXT_COLOR; + uint16_t params[6], colour = COLOR_WHITE; for (int i=0; i<6; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.drawTriangle(params[0], params[1], params[2], params[3], params[4], params[5], colour); @@ -7702,7 +6603,7 @@ object *fn_drawtriangle (object *args, object *env) { object *fn_filltriangle (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t params[6], colour = TEXT_COLOR; + uint16_t params[6], colour = COLOR_WHITE; for (int i=0; i<6; i++) { params[i] = checkinteger(car(args)); args = cdr(args); } if (args != NULL) colour = checkinteger(car(args)); tft.fillTriangle(params[0], params[1], params[2], params[3], params[4], params[5], colour); @@ -7722,7 +6623,7 @@ object *fn_filltriangle (object *args, object *env) { object *fn_drawchar (object *args, object *env) { (void) env; #if defined(gfxsupport) - uint16_t colour = TEXT_COLOR, bg = BG_COLOR, size = 1; + uint16_t colour = COLOR_WHITE, bg = COLOR_BLACK, size = 1; object *more = cdr(cddr(args)); if (more != NULL) { colour = checkinteger(car(more)); @@ -7842,6 +6743,109 @@ object *fn_invertdisplay (object *args, object *env) { return nil; } +// PicoCalc extras + +/* + (get-key) + Waits for a key press and returns it as a character. +*/ +char getKey () { + for (;;) { + if (pc_kbd.keyCount() > 0) { + const PCKeyboard::KeyEvent key = pc_kbd.keyEvent(); + if (key.state == PCKeyboard::StatePress) { + char temp = key.key; + if ((temp != 0) && (temp != 255) && (temp != 0xA1) && (temp != 0xA2) && (temp != 0xA3) && (temp != 0xA4) && (temp != 0xA5)) { + return temp; + } + } + } + } +} + +object *fn_getkey (object *args, object *env) { + (void) env, (void) args; + return character(getKey()); +} + +/* + (read-pixel x y) + Reads a pixel at coordinates (x,y) and returns the 5-6-5 colour value. +*/ +object *fn_readpixel (object *args, object *env) { + (void) env; + #if defined(gfxsupport) + return number(tft.readPixel(checkinteger(first(args)), checkinteger(second(args)))); + #else + (void) args; + #endif + return nil; +} + +/* + (save-bmp filename) + Saves the screen as a BMP file. +*/ +// Write two bytes, least significant byte first +void writeTwo (File SDfile, uint16_t word) { + SDfile.write(word & 0xFF); SDfile.write((word >> 8) & 0xFF); +} + +// Write four bytes, least significant byte first +void writeFour (File SDfile, uint32_t word) { + SDfile.write(word & 0xFF); SDfile.write((word >> 8) & 0xFF); + SDfile.write((word >> 16) & 0xFF); SDfile.write((word >> 24) & 0xFF); +} + +void savebmp (object *arg) { +#if defined(sdcardsupport) + uint16_t width = 320, height = 320; + SDBegin(); + File SDfile; + char buffer[BUFFERSIZE]; + SDfile = SD.open(MakeFilename(checkstring(arg), buffer), O_RDWR | O_CREAT | O_TRUNC); + // + // File header: 14 bytes + SDfile.write('B'); SDfile.write('M'); + writeFour(SDfile, 14+40+width*height*2); // File size in bytes + writeFour(SDfile, 0); + writeFour(SDfile, 14+40); // Offset to image data from start + // + // Image header: 40 bytes + writeFour(SDfile, 40); // Header size + writeFour(SDfile, width); // Image width + writeFour(SDfile, height); // Image height + writeTwo(SDfile, 1); // Planes + writeTwo(SDfile, 16); // Bits per pixel + writeFour(SDfile, 0); // Compression (none) + writeFour(SDfile, 0); // Image size (0 for uncompressed) + writeFour(SDfile, 0); // Preferred X resolution (ignore) + writeFour(SDfile, 0); // Preferred Y resolution (ignore) + writeFour(SDfile, 0); // Colour map entries (ignore) + writeFour(SDfile, 0); // Important colours (ignore) + // + // Image data: width * height * 2 bytes + for (int y=height-1; y>=0; y--) { + for (int x=0; x>1 | (rgb & 0x1F)); // Convert to 555 format + } + } + SDfile.close(); + SD.end(); +#else + (void) arg; + error2("not available"); + return 0; +#endif +} + +object *fn_savebmp (object *args, object *env) { + object *arg = first(args); + savebmp(arg); + return arg; +} + // Built-in symbol names const char string0[] = "nil"; const char string1[] = "t"; @@ -8089,187 +7093,25 @@ const char string242[] = "set-text-wrap"; const char string243[] = "fill-screen"; const char string244[] = "set-rotation"; const char string245[] = "invert-display"; -const char string246[] = ":led-builtin"; -const char string247[] = ":high"; -const char string248[] = ":low"; -#if defined(CPU_ATSAMD21) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-internal1v0"; -const char string255[] = ":ar-internal1v65"; -const char string256[] = ":ar-internal2v23"; -const char string257[] = ":ar-external"; -const char string258[] = ":pa-dir"; -const char string259[] = ":pa-dirclr"; -const char string260[] = ":pa-dirset"; -const char string261[] = ":pa-dirtgl"; -const char string262[] = ":pa-out"; -const char string263[] = ":pa-outclr"; -const char string264[] = ":pa-outset"; -const char string265[] = ":pa-outtgl"; -const char string266[] = ":pa-in"; -const char string267[] = ":pb-dir"; -const char string268[] = ":pb-dirclr"; -const char string269[] = ":pb-dirset"; -const char string270[] = ":pb-dirtgl"; -const char string271[] = ":pb-out"; -const char string272[] = ":pb-outclr"; -const char string273[] = ":pb-outset"; -const char string274[] = ":pb-outtgl"; -const char string275[] = ":pb-in"; -#elif defined(CPU_ATSAMD51) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-internal1v0"; -const char string255[] = ":ar-internal1v1"; -const char string256[] = ":ar-internal1v2"; -const char string257[] = ":ar-internal1v25"; -const char string258[] = ":ar-internal1v65"; -const char string259[] = ":ar-internal2v0"; -const char string260[] = ":ar-internal2v2"; -const char string261[] = ":ar-internal2v23"; -const char string262[] = ":ar-internal2v4"; -const char string263[] = ":ar-internal2v5"; -const char string264[] = ":ar-external"; -const char string265[] = ":pa-dir"; -const char string266[] = ":pa-dirclr"; -const char string267[] = ":pa-dirset"; -const char string268[] = ":pa-dirtgl"; -const char string269[] = ":pa-out"; -const char string270[] = ":pa-outclr"; -const char string271[] = ":pa-outset"; -const char string272[] = ":pa-outtgl"; -const char string273[] = ":pa-in"; -const char string274[] = ":pb-dir"; -const char string275[] = ":pb-dirclr"; -const char string276[] = ":pb-dirset"; -const char string277[] = ":pb-dirtgl"; -const char string278[] = ":pb-out"; -const char string279[] = ":pb-outclr"; -const char string280[] = ":pb-outset"; -const char string281[] = ":pb-outtgl"; -const char string282[] = ":pb-in"; -#elif defined(CPU_NRF51822) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-vbg"; -const char string255[] = ":ar-supply-one-half"; -const char string256[] = ":ar-supply-one-third"; -const char string257[] = ":ar-ext0"; -const char string258[] = ":ar-ext1"; -const char string259[] = ":p0-out"; -const char string260[] = ":p0-outset"; -const char string261[] = ":p0-outclr"; -const char string262[] = ":p0-in"; -const char string263[] = ":p0-dir"; -const char string264[] = ":p0-dirset"; -const char string265[] = ":p0-dirclr"; -#elif defined(CPU_NRF52840) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-internal"; -const char string255[] = ":ar-internal-3-0"; -const char string256[] = ":ar-internal-2-4"; -const char string257[] = ":ar-internal-1-8"; -const char string258[] = ":ar-internal-1-2"; -const char string259[] = ":ar-vdd4"; -const char string260[] = ":p0-out"; -const char string261[] = ":p0-outset"; -const char string262[] = ":p0-outclr"; -const char string263[] = ":p0-in"; -const char string264[] = ":p0-dir"; -const char string265[] = ":p0-dirset"; -const char string266[] = ":p0-dirclr"; -const char string267[] = ":p1-out"; -const char string268[] = ":p1-outset"; -const char string269[] = ":p1-outclr"; -const char string270[] = ":p1-in"; -const char string271[] = ":p1-dir"; -const char string272[] = ":p1-dirset"; -const char string273[] = ":p1-dirclr"; -#elif defined(CPU_NRF52833) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-internal"; -const char string255[] = ":ar-vdd4"; -const char string256[] = ":p0-out"; -const char string257[] = ":p0-outset"; -const char string258[] = ":p0-outclr"; -const char string259[] = ":p0-in"; -const char string260[] = ":p0-dir"; -const char string261[] = ":p0-dirset"; -const char string262[] = ":p0-dirclr"; -const char string263[] = ":p1-out"; -const char string264[] = ":p1-outset"; -const char string265[] = ":p1-outclr"; -const char string266[] = ":p1-in"; -const char string267[] = ":p1-dir"; -const char string268[] = ":p1-dirset"; -const char string269[] = ":p1-dirclr"; -#elif defined(CPU_iMXRT1062) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":output-opendrain"; -#elif defined(CPU_MAX32620) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":output"; -const char string252[] = ":default"; -const char string253[] = ":external"; -#elif defined(CPU_RP2040) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":gpio-in"; -const char string254[] = ":gpio-out"; -const char string255[] = ":gpio-out-set"; -const char string256[] = ":gpio-out-clr"; -const char string257[] = ":gpio-out-xor"; -const char string258[] = ":gpio-oe"; -const char string259[] = ":gpio-oe-set"; -const char string260[] = ":gpio-oe-clr"; -const char string261[] = ":gpio-oe-xor"; -#elif defined(CPU_RP2350) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":input-pulldown"; -const char string252[] = ":output"; -const char string253[] = ":gpio-in"; -const char string254[] = ":gpio-out"; -const char string255[] = ":gpio-out-set"; -const char string256[] = ":gpio-out-clr"; -const char string257[] = ":gpio-out-xor"; -const char string258[] = ":gpio-oe"; -const char string259[] = ":gpio-oe-set"; -const char string260[] = ":gpio-oe-clr"; -const char string261[] = ":gpio-oe-xor"; -#elif defined(CPU_RA4M1) -const char string249[] = ":input"; -const char string250[] = ":input-pullup"; -const char string251[] = ":output"; -const char string252[] = ":output-opendrain"; -const char string253[] = ":ar-default"; -const char string254[] = ":ar-internal"; -const char string255[] = ":ar-external"; -#endif +const char string246[] = "get-key"; +const char string247[] = "read-pixel"; +const char string248[] = "save-bmp"; +const char string249[] = ":led-builtin"; +const char string250[] = ":high"; +const char string251[] = ":low"; +const char string252[] = ":input"; +const char string253[] = ":input-pullup"; +const char string254[] = ":input-pulldown"; +const char string255[] = ":output"; +const char string256[] = ":gpio-in"; +const char string257[] = ":gpio-out"; +const char string258[] = ":gpio-out-set"; +const char string259[] = ":gpio-out-clr"; +const char string260[] = ":gpio-out-xor"; +const char string261[] = ":gpio-oe"; +const char string262[] = ":gpio-oe-set"; +const char string263[] = ":gpio-oe-clr"; +const char string264[] = ":gpio-oe-xor"; // Documentation strings const char doc0[] = "nil\n" @@ -8844,6 +7686,12 @@ const char doc244[] = "(set-rotation option)\n" "Sets the display orientation for subsequent graphics commands; values are 0, 1, 2, or 3."; const char doc245[] = "(invert-display boolean)\n" "Mirror-images the display."; +const char doc246[] = "(get-key)\n" +"Waits for a key press and returns it as a character."; +const char doc247[] = "(read-pixel x y)\n" +"Reads a pixel at coordinates (x,y) and returns the 5-6-5 colour value."; +const char doc248[] = "(save-bmp filename)\n" +"Saves the screen as a BMP file."; // Built-in symbol lookup table const tbl_entry_t lookup_table[] = { @@ -9093,187 +7941,25 @@ const tbl_entry_t lookup_table[] = { { string243, fn_fillscreen, 0201, doc243 }, { string244, fn_setrotation, 0211, doc244 }, { string245, fn_invertdisplay, 0211, doc245 }, - { string246, (fn_ptr_type)LED_BUILTIN, 0, NULL }, - { string247, (fn_ptr_type)HIGH, DIGITALWRITE, NULL }, - { string248, (fn_ptr_type)LOW, DIGITALWRITE, NULL }, -#if defined(CPU_ATSAMD21) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_INTERNAL1V0, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_INTERNAL1V65, ANALOGREFERENCE, NULL }, - { string256, (fn_ptr_type)AR_INTERNAL2V23, ANALOGREFERENCE, NULL }, - { string257, (fn_ptr_type)AR_EXTERNAL, ANALOGREFERENCE, NULL }, - { string258, (fn_ptr_type)&PORT->Group[0].DIR.reg, REGISTER, NULL }, - { string259, (fn_ptr_type)&PORT->Group[0].DIRCLR.reg, REGISTER, NULL }, - { string260, (fn_ptr_type)&PORT->Group[0].DIRSET.reg, REGISTER, NULL }, - { string261, (fn_ptr_type)&PORT->Group[0].DIRTGL.reg, REGISTER, NULL }, - { string262, (fn_ptr_type)&PORT->Group[0].OUT.reg, REGISTER, NULL }, - { string263, (fn_ptr_type)&PORT->Group[0].OUTCLR.reg, REGISTER, NULL }, - { string264, (fn_ptr_type)&PORT->Group[0].OUTSET.reg, REGISTER, NULL }, - { string265, (fn_ptr_type)&PORT->Group[0].OUTTGL.reg, REGISTER, NULL }, - { string266, (fn_ptr_type)&PORT->Group[0].IN.reg, REGISTER, NULL }, - { string267, (fn_ptr_type)&PORT->Group[1].DIR.reg, REGISTER, NULL }, - { string268, (fn_ptr_type)&PORT->Group[1].DIRCLR.reg, REGISTER, NULL }, - { string269, (fn_ptr_type)&PORT->Group[1].DIRSET.reg, REGISTER, NULL }, - { string270, (fn_ptr_type)&PORT->Group[1].DIRTGL.reg, REGISTER, NULL }, - { string271, (fn_ptr_type)&PORT->Group[1].OUT.reg, REGISTER, NULL }, - { string272, (fn_ptr_type)&PORT->Group[1].OUTCLR.reg, REGISTER, NULL }, - { string273, (fn_ptr_type)&PORT->Group[1].OUTSET.reg, REGISTER, NULL }, - { string274, (fn_ptr_type)&PORT->Group[1].OUTTGL.reg, REGISTER, NULL }, - { string275, (fn_ptr_type)&PORT->Group[1].IN.reg, REGISTER, NULL }, -#elif defined(CPU_ATSAMD51) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_INTERNAL1V0, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_INTERNAL1V1, ANALOGREFERENCE, NULL }, - { string256, (fn_ptr_type)AR_INTERNAL1V2, ANALOGREFERENCE, NULL }, - { string257, (fn_ptr_type)AR_INTERNAL1V25, ANALOGREFERENCE, NULL }, - { string258, (fn_ptr_type)AR_INTERNAL1V65, ANALOGREFERENCE, NULL }, - { string259, (fn_ptr_type)AR_INTERNAL2V0, ANALOGREFERENCE, NULL }, - { string260, (fn_ptr_type)AR_INTERNAL2V2, ANALOGREFERENCE, NULL }, - { string261, (fn_ptr_type)AR_INTERNAL2V23, ANALOGREFERENCE, NULL }, - { string262, (fn_ptr_type)AR_INTERNAL2V4, ANALOGREFERENCE, NULL }, - { string263, (fn_ptr_type)AR_INTERNAL2V5, ANALOGREFERENCE, NULL }, - { string264, (fn_ptr_type)AR_EXTERNAL, ANALOGREFERENCE, NULL }, - { string265, (fn_ptr_type)&PORT->Group[0].DIR.reg, REGISTER, NULL }, - { string266, (fn_ptr_type)&PORT->Group[0].DIRCLR.reg, REGISTER, NULL }, - { string267, (fn_ptr_type)&PORT->Group[0].DIRSET.reg, REGISTER, NULL }, - { string268, (fn_ptr_type)&PORT->Group[0].DIRTGL.reg, REGISTER, NULL }, - { string269, (fn_ptr_type)&PORT->Group[0].OUT.reg, REGISTER, NULL }, - { string270, (fn_ptr_type)&PORT->Group[0].OUTCLR.reg, REGISTER, NULL }, - { string271, (fn_ptr_type)&PORT->Group[0].OUTSET.reg, REGISTER, NULL }, - { string272, (fn_ptr_type)&PORT->Group[0].OUTTGL.reg, REGISTER, NULL }, - { string273, (fn_ptr_type)&PORT->Group[0].IN.reg, REGISTER, NULL }, - { string274, (fn_ptr_type)&PORT->Group[1].DIR.reg, REGISTER, NULL }, - { string275, (fn_ptr_type)&PORT->Group[1].DIRCLR.reg, REGISTER, NULL }, - { string276, (fn_ptr_type)&PORT->Group[1].DIRSET.reg, REGISTER, NULL }, - { string277, (fn_ptr_type)&PORT->Group[1].DIRTGL.reg, REGISTER, NULL }, - { string278, (fn_ptr_type)&PORT->Group[1].OUT.reg, REGISTER, NULL }, - { string279, (fn_ptr_type)&PORT->Group[1].OUTCLR.reg, REGISTER, NULL }, - { string280, (fn_ptr_type)&PORT->Group[1].OUTSET.reg, REGISTER, NULL }, - { string281, (fn_ptr_type)&PORT->Group[1].OUTTGL.reg, REGISTER, NULL }, - { string282, (fn_ptr_type)&PORT->Group[1].IN.reg, REGISTER, NULL }, -#elif defined(CPU_NRF51822) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_VBG, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_SUPPLY_ONE_HALF, ANALOGREFERENCE, NULL }, - { string256, (fn_ptr_type)AR_SUPPLY_ONE_THIRD, ANALOGREFERENCE, NULL }, - { string257, (fn_ptr_type)AR_EXT0, ANALOGREFERENCE, NULL }, - { string258, (fn_ptr_type)AR_EXT1, ANALOGREFERENCE, NULL }, - { string259, (fn_ptr_type)&NRF_GPIO->OUT, REGISTER, NULL }, - { string260, (fn_ptr_type)&NRF_GPIO->OUTSET, REGISTER, NULL }, - { string261, (fn_ptr_type)&NRF_GPIO->OUTCLR, REGISTER, NULL }, - { string262, (fn_ptr_type)&NRF_GPIO->IN, REGISTER, NULL }, - { string263, (fn_ptr_type)&NRF_GPIO->DIR, REGISTER, NULL }, - { string264, (fn_ptr_type)&NRF_GPIO->DIRSET, REGISTER, NULL }, - { string265, (fn_ptr_type)&NRF_GPIO->DIRCLR, REGISTER, NULL }, -#elif defined(CPU_NRF52840) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_INTERNAL, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_INTERNAL_3_0, ANALOGREFERENCE, NULL }, - { string256, (fn_ptr_type)AR_INTERNAL_2_4, ANALOGREFERENCE, NULL }, - { string257, (fn_ptr_type)AR_INTERNAL_1_8, ANALOGREFERENCE, NULL }, - { string258, (fn_ptr_type)AR_INTERNAL_1_2, ANALOGREFERENCE, NULL }, - { string259, (fn_ptr_type)AR_VDD4, ANALOGREFERENCE, NULL }, - { string260, (fn_ptr_type)&NRF_P0->OUT, REGISTER, NULL }, - { string261, (fn_ptr_type)&NRF_P0->OUTSET, REGISTER, NULL }, - { string262, (fn_ptr_type)&NRF_P0->OUTCLR, REGISTER, NULL }, - { string263, (fn_ptr_type)&NRF_P0->IN, REGISTER, NULL }, - { string264, (fn_ptr_type)&NRF_P0->DIR, REGISTER, NULL }, - { string265, (fn_ptr_type)&NRF_P0->DIRSET, REGISTER, NULL }, - { string266, (fn_ptr_type)&NRF_P0->DIRCLR, REGISTER, NULL }, - { string267, (fn_ptr_type)&NRF_P1->OUT, REGISTER, NULL }, - { string268, (fn_ptr_type)&NRF_P1->OUTSET, REGISTER, NULL }, - { string269, (fn_ptr_type)&NRF_P1->OUTCLR, REGISTER, NULL }, - { string270, (fn_ptr_type)&NRF_P1->IN, REGISTER, NULL }, - { string271, (fn_ptr_type)&NRF_P1->DIR, REGISTER, NULL }, - { string272, (fn_ptr_type)&NRF_P1->DIRSET, REGISTER, NULL }, - { string273, (fn_ptr_type)&NRF_P1->DIRCLR, REGISTER, NULL }, -#elif defined(CPU_NRF52833) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_INTERNAL, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_VDD4, ANALOGREFERENCE, NULL }, - { string256, (fn_ptr_type)&NRF_P0->OUT, REGISTER, NULL }, - { string257, (fn_ptr_type)&NRF_P0->OUTSET, REGISTER, NULL }, - { string258, (fn_ptr_type)&NRF_P0->OUTCLR, REGISTER, NULL }, - { string259, (fn_ptr_type)&NRF_P0->IN, REGISTER, NULL }, - { string260, (fn_ptr_type)&NRF_P0->DIR, REGISTER, NULL }, - { string261, (fn_ptr_type)&NRF_P0->DIRSET, REGISTER, NULL }, - { string262, (fn_ptr_type)&NRF_P0->DIRCLR, REGISTER, NULL }, - { string263, (fn_ptr_type)&NRF_P1->OUT, REGISTER, NULL }, - { string264, (fn_ptr_type)&NRF_P1->OUTSET, REGISTER, NULL }, - { string265, (fn_ptr_type)&NRF_P1->OUTCLR, REGISTER, NULL }, - { string266, (fn_ptr_type)&NRF_P1->IN, REGISTER, NULL }, - { string267, (fn_ptr_type)&NRF_P1->DIR, REGISTER, NULL }, - { string268, (fn_ptr_type)&NRF_P1->DIRSET, REGISTER, NULL }, - { string269, (fn_ptr_type)&NRF_P1->DIRCLR, REGISTER, NULL }, -#elif defined(CPU_iMXRT1062) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)OUTPUT_OPENDRAIN, PINMODE, NULL }, -#elif defined(CPU_MAX32620) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string252, (fn_ptr_type)DEFAULT, ANALOGREFERENCE, NULL }, - { string253, (fn_ptr_type)EXTERNAL, ANALOGREFERENCE, NULL }, -#elif defined(CPU_RP2040) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)(SIO_BASE+SIO_GPIO_IN_OFFSET), REGISTER, NULL }, - { string254, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_OFFSET), REGISTER, NULL }, - { string255, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_SET_OFFSET), REGISTER, NULL }, - { string256, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_CLR_OFFSET), REGISTER, NULL }, - { string257, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_XOR_OFFSET), REGISTER, NULL }, - { string258, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_OFFSET), REGISTER, NULL }, - { string259, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_SET_OFFSET), REGISTER, NULL }, - { string260, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_CLR_OFFSET), REGISTER, NULL }, - { string261, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_XOR_OFFSET), REGISTER, NULL }, -#elif defined(CPU_RP2350) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string253, (fn_ptr_type)(SIO_BASE+SIO_GPIO_IN_OFFSET), REGISTER, NULL }, - { string254, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_OFFSET), REGISTER, NULL }, - { string255, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_SET_OFFSET), REGISTER, NULL }, - { string256, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_CLR_OFFSET), REGISTER, NULL }, - { string257, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_XOR_OFFSET), REGISTER, NULL }, - { string258, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_OFFSET), REGISTER, NULL }, - { string259, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_SET_OFFSET), REGISTER, NULL }, - { string260, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_CLR_OFFSET), REGISTER, NULL }, - { string261, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_XOR_OFFSET), REGISTER, NULL }, -#elif defined(CPU_RA4M1) - { string249, (fn_ptr_type)INPUT, PINMODE, NULL }, - { string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, - { string251, (fn_ptr_type)OUTPUT, PINMODE, NULL }, - { string252, (fn_ptr_type)OUTPUT_OPENDRAIN, PINMODE, NULL }, - { string253, (fn_ptr_type)AR_DEFAULT, ANALOGREFERENCE, NULL }, - { string254, (fn_ptr_type)AR_INTERNAL, ANALOGREFERENCE, NULL }, - { string255, (fn_ptr_type)AR_EXTERNAL, ANALOGREFERENCE, NULL }, -#endif + { string246, fn_getkey, 0200, doc246 }, + { string247, fn_readpixel, 0222, doc247 }, + { string248, fn_savebmp, 0211, doc248 }, + { string249, (fn_ptr_type)LED_BUILTIN, 0, NULL }, + { string250, (fn_ptr_type)HIGH, DIGITALWRITE, NULL }, + { string251, (fn_ptr_type)LOW, DIGITALWRITE, NULL }, + { string252, (fn_ptr_type)INPUT, PINMODE, NULL }, + { string253, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL }, + { string254, (fn_ptr_type)INPUT_PULLDOWN, PINMODE, NULL }, + { string255, (fn_ptr_type)OUTPUT, PINMODE, NULL }, + { string256, (fn_ptr_type)(SIO_BASE+SIO_GPIO_IN_OFFSET), REGISTER, NULL }, + { string257, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_OFFSET), REGISTER, NULL }, + { string258, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_SET_OFFSET), REGISTER, NULL }, + { string259, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_CLR_OFFSET), REGISTER, NULL }, + { string260, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OUT_XOR_OFFSET), REGISTER, NULL }, + { string261, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_OFFSET), REGISTER, NULL }, + { string262, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_SET_OFFSET), REGISTER, NULL }, + { string263, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_CLR_OFFSET), REGISTER, NULL }, + { string264, (fn_ptr_type)(SIO_BASE+SIO_GPIO_OE_XOR_OFFSET), REGISTER, NULL }, }; #if !defined(extensions) @@ -9354,8 +8040,17 @@ bool findsubstring (char *part, builtin_t name) { } void testescape () { - // Context = NIL; - if (seriell->available() && seriell->read() == '~') { error2(PSTR("escape!")); } + static unsigned long n; + if (millis()-n < 500) return; + n = millis(); + if (Serial.available() && Serial.read() == '~') error2("escape!"); + if (pc_kbd.keyCount() > 0) { + const PCKeyboard::KeyEvent key = pc_kbd.keyEvent(); + if (key.state == PCKeyboard::StatePress) { + char c = key.key; + if (c == '~' || c == KEY_ESC) error2("escape!"); + } + } } /* @@ -9408,8 +8103,6 @@ object *eval (object *form, object *env) { EVAL: // Enough space? // Serial.println((uint32_t)sp - (uint32_t)&ENDSTACK); // Find best STACKDIFF value - // seriell->println((uint32_t)sp - (uint32_t)&ENDSTACK); // Find best STACKDIFF value - if (((uint32_t)sp - (uint32_t)&ENDSTACK) < STACKDIFF) { Context = NIL; error2("stack overflow"); } if (Freespace <= WORKSPACESIZE>>4) gc(form, env); // GC when 1/16 of workspace left // Escape @@ -9597,9 +8290,11 @@ object *eval (object *form, object *env) { */ void pserial (char c) { LastPrint = c; - if (!tstflag(NOECHO)) Display(c); // Don't display on T-Deck when paste in listing - if (c == '\n') seriell->write('\r'); - seriell->write(c); + if (!tstflag(NOECHO)) Display(c); // Don't display when paste in listing + #if defined (serialmonitor) + if (c == '\n') Serial.write('\r'); + Serial.write(c); + #endif } const char ControlCodes[] = "Null\0SOH\0STX\0ETX\0EOT\0ENQ\0ACK\0Bell\0Backspace\0Tab\0Newline\0VT\0" @@ -9834,6 +8529,7 @@ void plist (object *form, pfun_t pfun) { while (form != NULL && listp(form)) { pfun(' '); printobject(car(form), pfun); + testescape(); form = cdr(form); } if (form != NULL) { @@ -9882,109 +8578,200 @@ void prin1object (object *form, pfun_t pfun) { Flags = temp; } -// Read functions - -/* - glibrary - reads a character from the Lisp Library -*/ -int -glibrary() -{ - if (LastChar) { - char temp = LastChar; - LastChar = 0; - - return temp; - } - - char c = LispLibrary[GlobalStringIndex++]; - return (c != 0) ? c : -1; // -1? -} - -/* - loadfromlibrary - reads and evaluates a form from the Lisp Library -*/ -void -loadfromlibrary(object *env) -{ - GlobalStringIndex = 0; - object *line = read(glibrary); - while (line != NULL) { - protect(line); - eval(line, env); - unprotect(); - line = read(glibrary); - } -} - // PicoCalc terminal and keyboard support + +const int ScreenWidth = 320, ScreenHeight = 320; const int Columns = 53; const int Leading = 10; // Between 8 and 10 -const int Lines = 320/Leading; +const int Lines = ScreenHeight/Leading; const int LastColumn = Columns-1; const int LastLine = Lines-1; const char Cursor = 0x5f; -uint8_t Scroll = 0; - -// For line editor -const int TerminalWidth = 80; volatile int WritePtr = 0, ReadPtr = 0, LastWritePtr = 0; const int KybdBufSize = Columns*Lines; char KybdBuf[KybdBufSize], ScrollBuf[Columns][Lines]; volatile uint8_t KybdAvailable = 0; +uint8_t Scroll = 0; -// Parenthesis highlighting -void esc (int p, char c) { - seriell->write('\e'); seriell->write('['); - seriell->write((char)('0'+ p/100)); - seriell->write((char)('0'+ (p/10) % 10)); - seriell->write((char)('0'+ p % 10)); - seriell->write(c); +// Terminal ********************************************************************************** + +// Plot character at absolute character cell position +void PlotChar (uint8_t ch, uint8_t line, uint8_t column) { + #if defined(gfxsupport) + uint16_t y = line*Leading; + uint16_t x = column*6; + ScrollBuf[column][(line+Scroll) % Lines] = ch; + if (ch & 0x80) { + tft.drawChar(x, y, ch & 0x7f, TFT_BLACK, TFT_GREEN, 1); + } else { + tft.drawChar(x, y, ch & 0x7f, TFT_WHITE, TFT_BLACK, 1); + } +#endif } -void hilight (char c) { - seriell->write('\e'); seriell->write('['); seriell->write(c); seriell->write('m'); +// Clears the bottom line and then scrolls the display up by one line +void ScrollDisplay () { + #if defined(gfxsupport) + tft.fillRect(0, 320-Leading, 320, 10, TFT_BLACK); + for (uint8_t x = 0; x < Columns; x++) { + char c = ScrollBuf[x][Scroll]; + for (uint8_t y = 0; y < Lines-1; y++) { + char c2 = ScrollBuf[x][(y+Scroll+1) % Lines]; + if (c != c2) { + if (c2 & 0x80) { + tft.drawChar(x*6, y*Leading, c2 & 0x7f, TFT_BLACK, TFT_GREEN, 1); + } else { + tft.drawChar(x*6, y*Leading, c2 & 0x7f, TFT_WHITE, TFT_BLACK, 1); + } + c = c2; + } + } + } + // Tidy up graphics + for (uint8_t y = 0; y < Lines-1; y++) tft.fillRect(0, y*Leading+8, 320, 2, TFT_BLACK); + tft.fillRect(318, 0, 3, 320, TFT_BLACK); + for (int x=0; x= 17) && (c <= 20)) { // Parentheses + if (c == 17) PlotChar('(', line, column); + else if (c == 18) PlotChar('(' | 0x80, line, column); + else if (c == 19) PlotChar(')', line, column); + else PlotChar(')' | 0x80, line, column); + return; + } + // Hide cursor + PlotChar(' ', line, column); + if (c == 0x7F) { // DEL + if (column == 0) { + line--; column = LastColumn; + } else column--; + } else if ((c & 0x7f) >= 32) { // Normal character + PlotChar(c, line, column++); + if (column > LastColumn) { + column = 0; + if (line == LastLine) ScrollDisplay(); else line++; + } + // Control characters + } else if (c == 12) { // Clear display + tft.fillScreen(COLOR_BLACK); line = 0; column = 0; Scroll = 0; + for (int col = 0; col < Columns; col++) { + for (int row = 0; row < Lines; row++) { + ScrollBuf[col][row] = 0; + } + } + } else if (c == '\n') { // Newline + column = 0; + if (line == LastLine) ScrollDisplay(); else line++; + } else if (c == VT) { // Used by Lisp Screen Editor + column = 0; Scroll = 0; line = LastLine - 2; + } else if (c == BEEP) { playnote(0, 0, 4); delay(250); nonote(0); } // Beep + // Show cursor + PlotChar(Cursor, line, column); + #endif +} + +// Keyboard ********************************************************************************** + +void initkybd () { + Wire1.setSDA(6); + Wire1.setSCL(7); + Wire1.begin(); + Wire1.setClock(10000); + pc_kbd.begin(0x1f,&Wire1); +} + +int LastKeyword = 0; // For autocomplete + /* - Highlight - handles parenthesis highlighting with the line editor + autoComplete - autocompletes the string in the line editor with the next symbol from the table of built-in symbols. */ -void Highlight (int p, int wp, uint8_t invert) { - wp = wp + 2; // Prompt -#if defined (printfreespace) - int f = Freespace; - while (f) { wp++; f=f/10; } -#endif - int line = wp/TerminalWidth; - int col = wp%TerminalWidth; - int targetline = (wp - p)/TerminalWidth; - int targetcol = (wp - p)%TerminalWidth; - int up = line-targetline, left = col-targetcol; - if (p) { - if (up) esc(up, 'A'); - if (col > targetcol) esc(left, 'D'); else esc(-left, 'C'); - if (invert) hilight('7'); - seriell->write('('); seriell->write('\b'); - // Go back - if (up) esc(up, 'B'); // Down - if (col > targetcol) esc(left, 'C'); else esc(-left, 'D'); - seriell->write('\b'); seriell->write(')'); - if (invert) hilight('0'); +void autoComplete () { + static int bufIndex = 0, matchLen = 0, i = 0; + int gap = 0; + + // Only update what we're matching if we're not already looking through the buffer + if (LastKeyword == 0) { + i = 0; // Reset the search + for (matchLen = 0; matchLen < 32; matchLen++) { + int bufLoc = WritePtr - matchLen; + if ((KybdBuf[bufLoc] == ' ') || (KybdBuf[bufLoc] == '(') || (KybdBuf[bufLoc] == '\n')) { + // Move past those characters because we're not matching on them + bufIndex = bufLoc + 1; + matchLen--; + break; + } + // Do this test here in case the first character in the buffer is one of the characters we test for + else if (bufLoc == 0) { + bufIndex = bufLoc; + break; + } + } + } + + // Erase the previously shown keyword + for (int n=0; n 0) { WritePtr--; - seriell->write(8); seriell->write(' '); seriell->write(8); + Display(0x7F); if (WritePtr) c = KybdBuf[WritePtr-1]; } - } else if (c == 9) { // tab or ctrl-I - for (int i = 0; i < LastWritePtr; i++) Serial.write(KybdBuf[i]); + } else if (c == 209) { // shift-return + for (int i = 0; i < LastWritePtr; i++) Display(KybdBuf[i]); WritePtr = LastWritePtr; } else if (WritePtr < KybdBufSize) { + if (c == '"') string = !string; KybdBuf[WritePtr++] = c; - seriell->write(c); + Display(c); } -#if defined(vt100) // Do new parenthesis highlight - if (c == ')') { - int search = WritePtr-1, level = 0; + if (c == ')' && !string) { + int search = WritePtr-1, level = 0; bool string2 = false; while (search >= 0 && parenthesis == 0) { c = KybdBuf[search--]; - if (c == ')') level++; - if (c == '(') { + if (c == '"') string2 = !string2; + if (c == ')' && !string2) level++; + if (c == '(' && !string2) { level--; - if (level == 0) {parenthesis = WritePtr-search-1; wp = WritePtr; } + if (level == 0) parenthesis = WritePtr-search-1; } } - Highlight(parenthesis, wp, 1); + Highlight(parenthesis, 1); } -#endif return; } +// Read functions + +/* + glibrary - reads a character from the Lisp Library +*/ +int glibrary () { + if (LastChar) { + char temp = LastChar; + LastChar = 0; + return temp; + } + char c = LispLibrary[GlobalStringIndex++]; + return (c != 0) ? c : -1; // -1? +} /* - gserial - gets a character from the serial port + loadfromlibrary - reads and evaluates a form from the Lisp Library */ +void loadfromlibrary (object *env) { + GlobalStringIndex = 0; + object *line = read(glibrary); + while (line != NULL) { + protect(line); + eval(line, env); + unprotect(); + line = read(glibrary); + } +} + int gserial () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } -#if defined(lineeditor) + #if defined (serialmonitor) + unsigned long start = millis(); while (!KybdAvailable) { - if (seriell->available()) { - char temp = seriell->read(); - processkey(temp); - } - #if defined(i2ckbd) - if (pc_kbd.keyCount() > 0) { - const PCKeyboard::KeyEvent key = pc_kbd.keyEvent(); - if (key.state == PCKeyboard::StatePress) { + if (millis() - start > 1000) clrflag(NOECHO); + if (Serial.available()) { + char temp = Serial.read(); + if (temp != '\n' && !tstflag(NOECHO)) Serial.print(temp); + return temp; + } else { + // PicoCalc keyboard + if (pc_kbd.keyCount() > 0) { + const PCKeyboard::KeyEvent key = pc_kbd.keyEvent(); + if (key.state == PCKeyboard::StatePress) { char temp = key.key; - if ((temp != 0) && (temp !=255) && (temp != 0xA1) && (temp != 0xA2) && (temp != 0xA3) && (temp != 0xA4) && (temp != 0xA5)) { - ProcessKey(temp); + if (temp == '\t') autoComplete(); + else if ((temp != 0) && (temp != 255) && (temp != 0xA1) && (temp != 0xA2) && (temp != 0xA3) && (temp != 0xA4) && (temp != 0xA5)) { + ProcessKey(temp); LastKeyword = 0; } - } + } + } + } + } + if (ReadPtr != WritePtr) return KybdBuf[ReadPtr++]; + KybdAvailable = 0; + WritePtr = 0; + return '\n'; + #else + while (!KybdAvailable) { + // PicoCalc keyboard + if (pc_kbd.keyCount() > 0) { + const PCKeyboard::KeyEvent key = pc_kbd.keyEvent(); + if (key.state == PCKeyboard::StatePress) { + char temp = key.key; + if (temp == '\t') autoComplete(); + else if ((temp != 0) && (temp != 255) && (temp != 0xA1) && (temp != 0xA2) && (temp != 0xA3) && (temp != 0xA4) && (temp != 0xA5)) { + ProcessKey(temp); LastKeyword = 0; + } + } } - #endif } if (ReadPtr != WritePtr) return KybdBuf[ReadPtr++]; KybdAvailable = 0; WritePtr = 0; return '\n'; -#else - unsigned long start = millis(); - while (!seriell->available()) if (millis() - start > 1000) clrflag(NOECHO); - char temp = seriell->read(); - if (temp != '\n' && !tstflag(NOECHO)) pserial(temp); - return temp; #endif } @@ -10068,9 +8896,7 @@ int gserial () { */ object *nextitem (gfun_t gfun) { int ch = gfun(); - while(issp(ch)) { - ch = gfun(); - } + while(issp(ch)) ch = gfun(); if (ch == ';') { do { ch = gfun(); if (ch == ';' || ch == '(') setflag(NOECHO); } @@ -10227,195 +9053,12 @@ object *readrest (gfun_t gfun) { object *read (gfun_t gfun) { object *item = nextitem(gfun); if (item == (object *)KET) error2("incomplete list"); - if (item == (object *)BRA) { - return readrest(gfun); - } - if (item == (object *)DOT) { - return read(gfun); - } - if (item == (object *)QUO) { - return cons(bsymbol(QUOTE), cons(read(gfun), NULL)); - } + if (item == (object *)BRA) return readrest(gfun); + if (item == (object *)DOT) return read(gfun); + if (item == (object *)QUO) return cons(bsymbol(QUOTE), cons(read(gfun), NULL)); return item; } -// Terminal ********************************************************************************** - -// Plot character at absolute character cell position -void PlotChar (uint8_t ch, uint8_t line, uint8_t column) { - #if defined(gfxsupport) - uint16_t y = line*Leading; - uint16_t x = column*6; - ScrollBuf[column][(line+Scroll) % Lines] = ch; - if (ch & 0x80) { - tft.drawChar(x, y, ch & 0x7f, BG_COLOR, TEXT_COLOR, 1); - } else { - tft.drawChar(x, y, ch & 0x7f, TEXT_COLOR, BG_COLOR, 1); - } -#endif -} - -// Clears the bottom line and then scrolls the display up by one line -void ScrollDisplay () { - #if defined(gfxsupport) - tft.fillRect(0, 320-Leading, 320, 10, TFT_BLACK); - for (uint8_t x = 0; x < Columns; x++) { - char c = ScrollBuf[x][Scroll]; - for (uint8_t y = 0; y < Lines-1; y++) { - char c2 = ScrollBuf[x][(y+Scroll+1) % Lines]; - if (c != c2) { - if (c2 & 0x80) { - tft.drawChar(x*6, y*Leading, c2 & 0x7f, BG_COLOR, TFT_GREEN, 1); - } else { - tft.drawChar(x*6, y*Leading, c2 & 0x7f, TEXT_COLOR, BG_COLOR, 1); - } - c = c2; - } - } - } - // Tidy up graphics - for (uint8_t y = 0; y < Lines-1; y++) tft.fillRect(0, y*Leading+8, 320, 2, TFT_BLACK); - tft.fillRect(318, 0, 3, 320, TFT_BLACK); - for (int x=0; x= 17) && (c <= 20)) { // Parentheses - if (c == 17) PlotChar('(', line, column); - else if (c == 18) PlotChar('(' | 0x80, line, column); - else if (c == 19) PlotChar(')', line, column); - else PlotChar(')' | 0x80, line, column); - return; - } - if (c == STX) { invert = true; return; } - if (c == ETX) { invert = false; return; } - // Hide cursor - PlotChar(' ', line, column); - if (c == 0x7F) { // DEL - if (column == 0) { - line--; column = LastColumn; - } else column--; - } else if ((c & 0x7f) >= 32) { // Normal character - if (invert) PlotChar(c | 0x80, line, column++); else PlotChar(c, line, column++); - if (column > LastColumn) { - column = 0; - if (line == LastLine) ScrollDisplay(); else line++; - } - // Control characters - } else if (c == 12) { // Clear display - tft.fillScreen(COLOR_BLACK); line = 0; column = 0; Scroll = 0; - for (int col = 0; col < Columns; col++) { - for (int row = 0; row < Lines; row++) { - ScrollBuf[col][row] = 0; - } - } - } else if (c == '\n') { // Newline - column = 0; - if (line == LastLine) ScrollDisplay(); else line++; - } else if (c == VT) { - column = 0; Scroll = 0; line = LastLine - 2; - } else if (c == BEEP) tone(0, 440, 125); // Beep - // Show cursor - PlotChar(Cursor, line, column); - #endif -} - -// Keyboard ********************************************************************************** - -void initkybd () { -#ifdef ULISP_I2C1 - Wire1.setSDA(6); - Wire1.setSCL(7); - Wire1.begin(); - Wire1.setClock(10000); - pc_kbd.begin(0x1f,&Wire1); - #else - Wire.setSDA(4); - Wire.setSCL(5); - Wire.begin(); - Wire.setClock(10000); - pc_kbd.begin(); - #endif -} - - -// Parenthesis highlighting -void HighLight(int p, uint8_t invert) { - if (p) { - for (int n=0; n < p; n++) Display(8); - Display(17 + invert); - for (int n=1; n < p; n++) Display(9); - Display(19 + invert); - Display(9); - } -} -void ProcessKey (char c) { - static int parenthesis = 0; - if (c == 27) { setflag(ESCAPE); return; } // Escape key - // Undo previous parenthesis highlight - HighLight(parenthesis, 0); - parenthesis = 0; - // Edit buffer - if (c == '\n' || c == '\r') { - pserial('\n'); - KybdAvailable = 1; - ReadPtr = 0; - return; - } - if (c == 8 || c == 0x7f) { // Backspace key - if (WritePtr > 0) { - WritePtr--; - Display(0x7F); - if (WritePtr) c = KybdBuf[WritePtr-1]; - } - } else if (WritePtr < KybdBufSize) { - KybdBuf[WritePtr++] = c; - Display(c); - } - // Do new parenthesis highlight - if (c == ')') { - int search = WritePtr-1, level = 0; - while (search >= 0 && parenthesis == 0) { - c = KybdBuf[search--]; - if (c == ')') level++; - if (c == '(') { - level--; - if (level == 0) parenthesis = WritePtr-search-1; - } - } - HighLight(parenthesis, 1); - } - return; -} - - - // Setup /* @@ -10429,76 +9072,30 @@ void initenv () { /* initgfx - initialises the graphics */ -void -initgfx() -{ -#if defined(gfxsupport) -#if defined(ARDUINO_PYBADGE_M4) || defined(ARDUINO_PYGAMER_M4) - tft.initR(INITR_BLACKTAB); - tft.setRotation(1); - pinMode(TFT_BACKLIGHT, OUTPUT); - digitalWrite(TFT_BACKLIGHT, HIGH); - tft.fillScreen(0); -#elif defined(ARDUINO_WIO_TERMINAL) - tft.init(); - tft.setRotation(3); - tft.fillScreen(TFT_BLACK); -#elif defined(ARDUINO_NRF52840_CLUE) - tft.init(240, 240); - tft.setRotation(1); - tft.fillScreen(0); - pinMode(34, OUTPUT); // Backlight - digitalWrite(34, HIGH); -#elif defined(RASPBERRY_PI_PICO_PLATFORM) - tft.init(); -#if defined(PLATFORM_PICOCALC) - tft.setRotation(0); - tft.invertDisplay(1); -#endif - tft.fillScreen(TFT_BLACK); - tft.setTextColor(TEXT_COLOR); -#endif -#endif +void initgfx () { + #if defined(gfxsupport) + tft.init(); + tft.writecommand(TFT_DISPOFF); + tft.invertDisplay(1); + tft.fillScreen(TFT_BLACK); + tft.writecommand(TFT_DISPON); + #endif } void setup () { Serial.begin(9600); - #ifdef ULISP_SERIAL1 - seriell = &Serial1; - #else - seriell = &Serial; - #endif - - seriell->begin(BAUDRATE*100); - int start = millis(); - - while ((millis() - start) < 5000) { - #ifdef ULISP_SERIAL1 - if (Serial1) break; - #else - if (Serial) break; - #endif - } - -#if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2W) -#if defined(sdcardsupport) && defined(PLATFORM_PICOCALC) - // picocalc doesn't have touch screen - pinMode(SDCARD_SS_PIN,OUTPUT); + while ((millis() - start) < 5000) { if (Serial) break; } + #if defined(sdcardsupport) + pinMode(SDCARD_SS_PIN, OUTPUT); digitalWrite(SDCARD_SS_PIN,1); -#endif -#endif - - + #endif initworkspace(); initenv(); initsleep(); initgfx(); -#if defined(i2ckbd) initkybd(); -#endif - pfstring(PSTR("uLisp 4.7b "), pserial); pln(pserial); - loadimage(NULL); + pfstring(PSTR("uLisp 4.7d "), pserial); pln(pserial); } // Read/Evaluate/Print loop @@ -10521,7 +9118,7 @@ void repl (object *env) { Context = NIL; object *line = read(gserial); #if defined(CPU_NRF52840) - seriell->flush(); + Serial.flush(); #endif // Break handling if (BreakLevel) { @@ -10551,27 +9148,22 @@ void repl (object *env) { /* loop - the Arduino IDE main execution loop */ -void -loop() -{ - if (!setjmp(toplevel_handler)) { -#if defined(resetautorun) - volatile int autorun = 12; // Fudge to keep code size the same -#else - volatile int autorun = 13; -#endif - if (autorun == 12) { - autorunimage(); - } - } - - ulisperror(); - repl(NULL); +void loop () { + if (!setjmp(toplevel_handler)) { + #if defined(resetautorun) + volatile int autorun = 12; // Fudge to keep code size the same + #else + volatile int autorun = 13; + #endif + if (autorun == 12) autorunimage(); + } + ulisperror(); + repl(NULL); } void ulisperror () { // Come here after error - delay(100); while (seriell->available()) seriell->read(); + delay(100); while (Serial.available()) Serial.read(); clrflag(NOESC); BreakLevel = 0; TraceStart = 0; TraceTop = 0; for (int i=0; i>4) * 10) + (n&0x0f); -} - -/* - * STANDARD DEFINITIONS - * - * These definitions should be the same on every platform. - */ -object * -fn_platform(object *args, object *env) -{ - (void) args; - (void) env; - -#if defined(PLATFORM_PICOCALC) - const char platformName[] = ":picocalc"; -#elif defined(TDECK_PERI_POWERON) /* first t-deck define */ - const char platformName[] = ":t-deck"; -#elif defined(ARDUINO_TEENSY41) - const char platformName[] = ":teensy41"; -#else - const char platformName[] = ":unknown"; -#endif - return internlong((char *)platformName); -} - -object * -fn_bcd_to_dec(object *args, object *env) -{ - (void) env; - - object *arg = car(args); - - int n = checkinteger(arg); - if ((n < 0) || (n > 153)) { - error2("number not in the range [0...#x99]."); - } - - uint8_t result = bcd_to_dec(static_cast(n)); - return number(static_cast(result)); -} - -object * -fn_dec_to_bcd(object *args, object *env) -{ - (void) env; - - object *arg = car(args); - - int n = checkinteger(arg); - if ((n < 0) || (n > 99)) { - error2("number not in the range [0...99]."); - } - - uint8_t result = dec_to_bcd(static_cast(n)); - return number(static_cast(result)); -} - -object * -fn_now(object *args, object *env) -{ - (void) env; - static unsigned long Offset; - unsigned long now = millis()/1000; - int nargs = listlength(args); - - // Set time - if (nargs == 3) { - Offset = (unsigned long)((checkinteger(first(args))*60 \ - + checkinteger(second(args)))*60 \ - + checkinteger(third(args)) - now); - } else if (nargs > 0) { - error2(PSTR("wrong number of arguments")); - } - - // Return time - unsigned long secs = Offset + now; - object *seconds = number(secs%60); - object *minutes = number((secs/60)%60); - object *hours = number((secs/3600)%24); - - return cons(hours, cons(minutes, cons(seconds, NULL))); -} - - -void -hyperprint(object *form, int lm, pfun_t pfun) -{ - if (atom(form)) { - if (isbuiltin(form, NOTHING)) { - printsymbol(form, pfun); - } else { - printobject(form, pfun); - } - } else if (quoted(form)) { - pfun('\''); - hyperprint(car(cdr(form)), lm + 1, pfun); - } else { - lm = lm + PPINDENT; - bool fits = (subwidth(form, PPWIDTH - lm - PPINDENT) >= 0); - int special = 0, extra = 0; bool separate = true; - object *arg = car(form); - - if (symbolp(arg) && builtinp(arg->name)) { - uint8_t minmax = getminmax(builtin(arg->name)); - if (minmax == 0327 || minmax == 0313) { - special = 2; // defun, setq, setf, defvar - } else if (minmax == 0317 || minmax == 0017 || - minmax == 0117 || minmax == 0123) { - special = 1; - } - } - - while (form != NULL) { - if (atom(form)) { - pfstring(PSTR(" . "), pfun); - printobject(form, pfun); - pfun(')'); - return; - } else if (separate) { - pfun('('); - separate = false; - } else if (special) { - pfun(' '); - special--; - } else if (fits) { - pfun(' '); - } else { - pln(pfun); - indent(lm, ' ', pfun); - } - - hyperprint(car(form), lm+extra, pfun); - form = cdr(form); - } - pfun(')'); - } -} - -object * -fn_sym_def(object *args, object *env) -{ - (void) env; - - object *obj = first(args); - pfun_t pfun = pstreamfun(cdr(args)); -#if defined(gfxsupport) - if (pfun == gfxwrite) ppwidth = GFXPPWIDTH; -#endif - object *pair = findvalue(obj, env); - object *var = car(pair); - object *val = cdr(pair); - pln(pfun); - - if (consp(val) && symbolp(car(val)) && builtin(car(val)->name) == LAMBDA) { - hyperprint(cons(bsymbol(DEFUN), cons(var, cdr(val))), 0, pfun); - } else { - hyperprint(cons(bsymbol(DEFVAR), cons(var, cons(quote(val), NULL))), 0, pfun); - } - - pln(pfun); - ppwidth = PPWIDTH; - return bsymbol(NOTHING); -} - - ->>>>>>> 5392bac (moving to project folder) -object * -fn_listlibrary2(object *args, object *env) -{ - (void) args, (void) env; - object *lst = nil; - - GlobalStringIndex = 0; - object *line = read(glibrary); - while (line != NULL) { - builtin_t bname = builtin(first(line)->name); - if (bname == DEFUN || bname == DEFVAR) { - lst = cons(second(line), lst); - } - line = read(glibrary); - } - - return lst; -} - - -object * -fn_lambdap(object *arg, object *env) -{ - (void) env; - - if (consp(arg)) { - arg = car(arg); - } - - if (builtin(arg->name) == LAMBDA) { - return tee; - } - - return nil; -} - - -object * -fn_searchstr(object *args, object *env) -{ - (void) env; - - int startpos = 0; - object *pattern = first(args); - object *target = second(args); - args = cddr(args); - - if (pattern == NULL) { - return number(0); - } else if (target == NULL) { - return nil; - } - - if (args != NULL) { - startpos = checkinteger(car(args)); - } - - if (stringp(pattern) && stringp(target)) { - int l = stringlength(target); - int m = stringlength(pattern); - - if (startpos > l) { - error2(indexrange); - } - - for (int i = startpos; i <= l-m; i++) { - int j = 0; - while (j < m && nthchar(target, i+j) == nthchar(pattern, j)) { - j++; - } - - if (j == m) { - return number(i); - } - } - return nil; - } else { - error2("arguments are not both lists or strings"); - } - - return nil; -} - - -object * -fn_searchn(object *args, object *env) -{ - (void) env; - - int matches = 0; - int last_index = 0; - object *pattern = first(args); - object *target = second(args); - - if (cddr(args) != NULL) { - object *num = third(args); - - if (integerp(num)) { - matches = num->integer; - } - } - - if (pattern == NULL) { - return number(0); - } else if (target == NULL) { - return nil; - } else if (listp(pattern) && listp(target)) { - int l = listlength(target); - int m = listlength(pattern); - - for (int i = 0; i <= l-m; i++) { - object *target1 = target; - while (pattern != NULL && eq(car(target1), car(pattern))) { - pattern = cdr(pattern); - target1 = cdr(target1); - } - - if (pattern == NULL){ - last_index = i; - - if (matches-- == 0) { - return number(i); - } - } - pattern = first(args); target = cdr(target); - } - - if (last_index > 0) { - return number(last_index); - } - return nil; - } else if (stringp(pattern) && stringp(target)) { - int l = stringlength(target); - int m = stringlength(pattern); - - for (int i = 0; i <= l-m; i++) { - int j = 0; - while (j < m && nthchar(target, i+j) == nthchar(pattern, j)) { - j++; - } - - if (j == m) { - last_index = i; - if(matches-- == 0){ - return number(i); - } - } - } - - if (last_index > 0) { - return number(last_index); - } - - return nil; - } else { - error2(PSTR("arguments are not both lists or strings")); - } - - return nil; -} - - -// SD card standard library. - -#if defined(sdcardsupport) -object * -fn_sd_rename(object *args, object *env) -{ - (void) env; - char buffer1[BUFFERSIZE]; - char buffer2[BUFFERSIZE]; - - object *pathFrom = car(args); - if (!stringp(pathFrom)) { - error2("filenames must be strings."); - } - - object *pathTo = car(cdr(args)); - if (!stringp(pathTo)) { - error2("filenames must be strings."); - } - - if (!SD.rename((const char *)MakeFilename(pathFrom, buffer1), - (const char *)MakeFilename(pathTo, buffer2))) { - return nil; - } - - return tee; -} - -object * -fn_sd_remove(object *args, object *env) -{ - (void) env; - char buffer[BUFFERSIZE]; - - object *arg = car(args); - if (!SD.remove(MakeFilename(arg, buffer))) { - return nil; - } - - return tee; -} - -object * -fn_sd_existsp(object *args, object *env) -{ - (void) env; - - char buffer[BUFFERSIZE]; - object *arg = car(args); - if (!SD.exists(MakeFilename(arg, buffer))) { - return nil; - } - - return tee; -} - -/* - (sd-make-dir path) - Create a directory on the SD card. - This will also create any intermediate directories that don’t already exists; - e.g. SD.mkdir("a/b/c") will create a, b, and c. - */ -object * -fn_sd_mkdir(object *args, object *env) -{ - (void) env; - - char buffer[BUFFERSIZE]; - object *arg = car(args); - - if (SD.mkdir(MakeFilename(arg, buffer))) { - return tee; - } - - return nil; -} - - -/* - (sd-remove-dir path) - Remove a directory from the SD card. The directory must be empty. - */ -object * -fn_sd_rmdir(object *args, object *env) -{ - (void) env; - - char buffer[BUFFERSIZE]; - object *arg = car(args); - - if (SD.rmdir(MakeFilename(arg, buffer))) { - return tee; - } - - return nil; -} - - -/* - * (sd-list) - */ -object * -fn_sd_list(object *args, object *env) -{ - (void) env; - - SDBegin(); - char *sd_path_buf = NULL; - File root; - object *result = cons(NULL, NULL); - object *ptr = result; - - if (args != NULL) { - object *arg1 = checkstring(first(args)); - int len = stringlength(arg1) + 2; //make it longer for the initial slash and the null terminator - - sd_path_buf = (char*)malloc(len); - if (sd_path_buf != NULL) { - cstring(arg1, &sd_path_buf[1], len-1); - sd_path_buf[0] = '/'; //really weird way to add a slash at the front... - root = SD.open(sd_path_buf); - } - } else{ - root = SD.open("/"); - } - - while (true) { - File entry = root.openNextFile(); - if (!entry) { - break; // no more files - } - object *filename = lispstring((char*)entry.name()); - - if (entry.isDirectory()) { - cdr(ptr) = cons(filename, NULL); - } else{ - cdr(ptr) = cons(cons(filename, number(entry.size())), NULL); - } - - ptr = cdr(ptr); - entry.close(); - } - - if (sd_path_buf != NULL) { - free(sd_path_buf); - } - - root.close(); - return cdr(result); -} -#endif - - -/* - * PICOCALC-SPECIFIC FUNCTIONS - * - * Only works on the PicoCalc... - */ -#if defined(PLATFORM_PICOCALC) -char -getkey() -{ - PCKeyboard::KeyEvent kevt; - char keypress; - - do { - kevt = pc_kbd.keyEvent(); - - if (kevt.state == PCKeyboard::StatePress) { - if (kevt.key == 6) { - continue; - } - - keypress = kevt.key; - break; - } - } while (pc_kbd.keyCount() == 0); - - - do { - kevt = pc_kbd.keyEvent(); - } while (kevt.state != PCKeyboard::StateRelease); - - switch (keypress) { - case 177: - keypress = 27; - break; - default: - // do nothing - break; - } - - return keypress; -} - -object * -fn_get_key(object *args, object *env) -{ - (void) args; - (void) env; - - return character(getkey()); -} -#endif - - -#if defined(TDECK_PERI_POWERON) -#define touchscreen - -#if defined(touchscreen) -#include "TouchDrvGT911.hpp" -TouchDrvGT911 touch; -#endif - -#define TDECK_TOUCH_INT 16 - -#define TDECK_TRACKBALL_UP 3 -#define TDECK_TRACKBALL_DOWN 15 -#define TDECK_TRACKBALL_LEFT 1 -#define TDECK_TRACKBALL_RIGHT 2 -#define PLATFORM_TDECK - -volatile int ball_val = 0; - -// Touchscreen -void -initTouch() -{ -#if defined (touchscreen) - pinMode(TDECK_TOUCH_INT, INPUT); - touch.setPins(-1, TDECK_TOUCH_INT);\ - //keyboard already initialized the I2C? - if (!touch.begin(Wire1, GT911_SLAVE_ADDRESS_L)) { - while (1) { - Serial.println("Failed to find GT911 - check your wiring!"); - delay(1000); - } - } - // Set touch max xy - touch.setMaxCoordinates(320, 240); - // Set swap xy - touch.setSwapXY(true); - // Set mirror xy - touch.setMirrorXY(false, true); -#endif -} - - -void -ISR_trackball_up() -{ - ball_val = 218; -} - -void -ISR_trackball_down() -{ - ball_val = 217; -} - -void -ISR_trackball_left() -{ - ball_val = 216; -} - -void -ISR_trackball_right () -{ - ball_val = 215; -} - -void -inittrackball() -{ - pinMode(TDECK_TRACKBALL_UP, INPUT_PULLUP); - pinMode(TDECK_TRACKBALL_DOWN, INPUT_PULLUP); - pinMode(TDECK_TRACKBALL_LEFT, INPUT_PULLUP); - pinMode(TDECK_TRACKBALL_RIGHT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_UP), ISR_trackball_up, FALLING); - attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_DOWN), ISR_trackball_down, FALLING); - attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_LEFT), ISR_trackball_left, FALLING); - attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_RIGHT), ISR_trackball_right, FALLING); -} - -object * -fn_get_touch_points(object *args, object *env) -{ -#if defined(touchscreen) - int16_t x[5], y[5]; - uint8_t touched = 0; - object *result = nil; - do { - touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); - if (touched > 0) { - //start from the end of the list so we dont have to reverse it - for (int i = touched; i > 0; --i) { - result = cons(cons(number(x[i-1]), number(y[i-1])), result); - } - } - } while(touch.isPressed()); - return result; - -#else - return nil; -#endif -} - -bool -isScreenTouched() -{ - bool received_touch = false; - - // Clear any previous readings since it buffers those. - do { - int16_t x[5], y[5]; - uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); - } while(touch.isPressed()); - - // touch.ispressed() will trigger like 5 times if you press it once so - // we have to loop through it and get the touchpoints - do { - int16_t x[5], y[5]; - uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); - if (touched > 0) { - received_touch = true; - } - } while(touch.isPressed()); - - return received_touch; -} - - -// T-Deck extras -char -touchKeyModEditor(char temp) -{ -#if defined (touchscreen) - /* t-deck / blackberry keyboard missing symbols - missing mapped alt symbol - ` k ' - ~ p @ - % $ - ^ a * - & q # - = o + - < t ( - > y ) - \ u _ - | g / - - [ alt-t ( - ] alt-y ) - - { n/a - } n/a - tab space - - while holding the touch screen - c --- quit editor and return to REPL - n --- discard current text buffer (i.e. new file) - backspace --- delete line starting at cursor position - trackball left --- move cursor to start of line - trackball right --- move cursor to end of line - ^ --- move cursor to beginning of buffer - trackball up / trackball down --- move one page up or down - - Fn-h --- help menu - Fn-( --- toggle bracket matching on/off - Fn-) --- check if bracket under the cursor has a matching bracket - in the buffer. If so, they are temporarily highlighted. - (Use when continuous bracket matching is off.) - Fn-b --- bind contents of the text buffer to a symbol of your choice and quit editor - Fn-d --- delete a file on the SD card - Fn-s --- save text buffer to SD card - Fn-l --- load text from SD card into buffer, discarding the present one - Fn-i --- show directory of SD card - - */ - - if (isScreenTouched()) { - if (temp == 'k') return '`'; - else if (temp == 'p') return '~'; - else if (temp == '$') return '%'; - else if (temp == 'a') return '^'; - else if (temp == 'q') return '&'; - else if (temp == 'o') return '='; - else if (temp == 't') return '<'; - else if (temp == 'y') return '>'; - else if (temp == 'u') return '\\'; - else if (temp == 'g') return '|'; - else if (temp == '(') return '['; - else if (temp == ')') return ']'; - else if (temp == ' ') return '\t'; - - else if (temp == 'c') return (char)17; //quit - else if (temp == 'n') return (char)24; //new - else if (temp == 8) return (char)12; //delete line - else if (temp == '*') return (char)94; //beginning - else if (temp == 'h') return (char)16; //help - else if (temp == 's') return (char)203; //save - else if (temp == 'l') return (char)204; //load - else if (temp == 'd') return (char)202; //delete - else if (temp == 'b') return (char)198; //bind - else if (temp == 'i') return (char)205; //show dir - else if (temp == '1') return (char)194; //toggle bracket - else if (temp == '2') return (char)195; //highlight - - } -#else - if (temp == '@') temp = '~'; - if (temp == '_') temp = '\\'; -#endif - return temp; -} - - -object * -fn_KeyboardGetKey(object *args, object *env) -{ - (void) env, (void) args; - - Wire1.requestFrom(0x55, 1); - if (Wire1.available()) { - char temp = Wire1.read(); - if ((temp != 0) && (temp !=255)){ - temp = touchKeyModEditor(temp); - //Serial.println((int)temp); - return number(temp); - } - } - - if (ball_val != 0) { - int temp = ball_val; - ball_val = 0; - if (isScreenTouched()) { - // ((or 1 210) (se:linestart)) - // ((or 5 213) (se:lineend)) - // (211 (se:prevpage)) - // (214 (se:nextpage)) - switch(temp){ - case 218: temp = 211; break; //up - case 217: temp = 214; break; //down - case 216: temp = 210; break; //left - case 215: temp = 213; break; //right - } - } - return number(temp); - } - return nil; -} - - -/* - (keyboard-flush) - Discard missing key up/down events. - */ -object * -fn_KeyboardFlush(object *args, object *env) -{ - (void) args, (void) env; - return nil; -} -#endif - - - -/* - * SYMBOL NAMES - * - * Define symbol names as const char[] PROGMEM here. - */ -const char stringlambdap[] PROGMEM = "lambdap"; -const char stringnow[] PROGMEM = "now"; -const char string_sym_def[] PROGMEM = "symdef"; -const char stringbcd_to_dec[] PROGMEM = "bcd-to-dec"; -const char stringdec_to_bcd[] PROGMEM = "dec-to-bcd"; -const char stringlist_library2[] PROGMEM = "list-library2"; -const char stringplatform[] PROGMEM = "platform"; -const char stringSearchStr[] PROGMEM = "search-str"; -const char stringsearchn[] PROGMEM = "searchn"; - -#if defined(sdcardsupport) -const char stringsd_rename[] PROGMEM = "sd-rename"; -const char stringsd_remove[] PROGMEM = "sd-remove"; -const char stringsd_existsp[] PROGMEM = "sd-exists-p"; -const char stringsd_mkdir[] PROGMEM = "sd-make-dir"; -const char stringsd_rmdir[] PROGMEM = "sd-remove-dir"; -const char stringsd_dir[] PROGMEM = "sd-list"; -#endif - -#if defined(PLATFORM_PICOCALC) -const char string_get_key[] PROGMEM = "get-key"; - -#elif defined(TDECK_PERI_POWERON) -const char string_gettouchpoints[] PROGMEM = "get-touch-points"; -const char stringKeyboardGetKey[] PROGMEM = "keyboard-get-key"; -const char stringKeyboardFlush[] PROGMEM = "keyboard-flush"; -#endif - - -/* - * DOCUMENTATION STRINGS - * - * Define documentation strings as const char[] PROGMEM here. - */ - -const char doclambdap[] PROGMEM = "(lambdap x)" -"Returns t if the form passed in is a lambda."; - -const char docnow[] PROGMEM = "(now [hh mm ss])\n" -"Sets the current time, or with no arguments returns the current time\n" -"as a list of three integers (hh mm ss)."; - -const char doc_sym_def[] PROGMEM = "(symbol-def symbol [str])\n" -"Prints the definition of a symbol (variable or function) defined in\n" -"ulisp using the pretty printer." -"If str is specified it prints to the specified stream.\n" -"It returns no value."; - -const char doc_bcd_to_dec[] PROGMEM = "(bcd-to-dec n)\n" -"Convert the BCD-encoded number n to decimal."; - -const char doc_dec_to_bcd[] PROGMEM = "(dec-to-bcd n)\n" -"BCD encode n."; - -const char doc_list_library2[] PROGMEM = "(list-library2)\n" -"Return a list of all symbols in the current Lisp library."; - -const char doc_platform[] PROGMEM = "(platform)\n" -"Returns a keyword with the current platform. Supports :picocalc,\n" -":t-deck, and :teensy41. Otherwise, returns :unknown."; - -const char docSearchStr[] PROGMEM = "(search pattern target [startpos])\n" -"Returns the index of the first occurrence of pattern in target, or nil if it's not found\n" -"starting from startpos"; - -const char docsearchn[] PROGMEM = "(searchn pattern target [n])\n" -"Returns the index of the nth occurrence of pattern in target,\n" -"which can be lists or strings, or nil if it's not found.\n" -"if the pattern occured more than once but less than n times, it returns the last occuring index"; - - -// SD card doc strings -#if defined(sdcardsupport) -const char docsd_rename[] PROGMEM = "(sd-rename from to)\n" -"Renames the file named by 'from' to 'to.'"; - -const char docsd_remove[] PROGMEM = "(sd-remove file)\n" -"Removes the named file from the filesystem. Returns t if the file\n" -"was remove successfully."; - -const char docsd_existsp[] PROGMEM = "(sd-exists-p file)\n" -"Returns t if the named file exists."; - -const char docsd_dir[] PROGMEM = "(sd-list [directory])\n" -"Returns a list of filenames in the root or named directory."; - -const char docsd_mkdir[] PROGMEM = "(sd-make-dir directory)\n" -"Create a directory with the specified name. Returns t if \n" -"successful, otherwise nil."; - -const char docsd_rmdir[] PROGMEM = "(sd-remove-dir directory)\n" -"Remove the named directory. Returns t if successful, otherwise nil."; -#endif - - -// PicoCalc-specific doc strings -#if defined(PLATFORM_PICOCALC) -const char doc_get_key[] PROGMEM = "(get-key)\n" -"Waits for a keypress event, then returns the key."; - -// T-Deck-specific doc strings -#elif defined(TDECK_PERI_POWERON) -const char doc_gettouchpoints[] PROGMEM = "(get-touch-points)\n" -"Returns all the points being touched on the screen in a list of x,y pairs or an empty list"; - -const char docKeyboardGetKey[] PROGMEM = "(keyboard-get-key [pressed])\n" -"Get key last recognized - default: when released, if [pressed] is t: when pressed)."; -const char docKeyboardFlush[] PROGMEM = "(keyboard-flush)\n" -"Discard missing key up/down events."; - -// End of platform-specific doc strings. -#endif - - -// Symbol lookup table -const tbl_entry_t lookup_table2[] PROGMEM = { - { stringlambdap, fn_lambdap, 0211, doclambdap }, - { stringnow, fn_now, 0203, docnow }, - { string_sym_def, fn_sym_def, 0212, doc_sym_def }, - { stringbcd_to_dec, fn_bcd_to_dec, 0211, doc_bcd_to_dec }, - { stringdec_to_bcd, fn_dec_to_bcd, 0211, doc_dec_to_bcd }, - { stringlist_library2, fn_listlibrary2, 0200, doc_list_library2 }, - { stringplatform, fn_platform, 0200, doc_platform }, - { stringSearchStr, fn_searchstr, 0224, docSearchStr }, - { stringsearchn, fn_searchn, 0223, docsearchn }, - -#if defined(sdcardsupport) - { stringsd_rename, fn_sd_rename, 0222, docsd_rename }, - { stringsd_remove, fn_sd_remove, 0211, docsd_remove }, - { stringsd_existsp, fn_sd_existsp, 0211, docsd_existsp }, - { stringsd_dir, fn_sd_list, 0201, docsd_dir }, - { stringsd_mkdir, fn_sd_mkdir, 0211, docsd_mkdir }, - { stringsd_rmdir, fn_sd_rmdir, 0211, docsd_rmdir }, -#endif - -#if defined(PLATFORM_PICOCALC) - { string_get_key, fn_get_key, 0200, doc_get_key }, - -#elif defined(TDECK_PERI_POWERON) - { string_gettouchpoints, fn_get_touch_points, 0200, doc_gettouchpoints }, - { stringKeyboardGetKey, fn_KeyboardGetKey, 0201, docKeyboardGetKey }, - { stringKeyboardFlush, fn_KeyboardFlush, 0200, docKeyboardFlush }, - -#endif -}; - -// Table cross-reference functions - -tbl_entry_t *tables[] = {lookup_table, lookup_table2}; -const unsigned int tablesizes[] = { arraysize(lookup_table), arraysize(lookup_table2) }; - -const tbl_entry_t * -table(int n) -{ - return tables[n]; -} - -unsigned int -tablesize(int n) -{ - return tablesizes[n]; -}