adding some functions

This commit is contained in:
Kyle Isom 2025-04-09 20:46:40 -07:00
parent 268b8f2ee2
commit 2cb940a546
5 changed files with 342 additions and 69 deletions

View File

@ -180,6 +180,33 @@ Appends item to list destructively; lst will be altered with
itm appended to the end of the list."
(nconc lst (list itm)))
(defun user-symbols ()
"(user-symbols)
Returns a list of all the symbols add by a user after boot."
(let ((library (list-library2)))
(remove-if (lambda (sym) (member sym library)) (globals))))
(defun reset-user-environment ()
"(reset-user-environment)
Removes all user-defined symbols."
(mapcar 'makunbound (user-symbols)))
(defun keyword-string (k)
"(keyword-string k)
Returns the keyword as a string, or nil if the arg isn't a keyword."
(when (keywordp k)
(subseq (string k) 1)))
(defun load-platform ()
"(load-platform)
Load-platform specific code if present, found on the SD card as
platform.lsp (e.g. picocalc.lsp)."
(let ((platform-file (concatenate 'string (keyword-string (platform)) ".lsp")))
(when (sd-exists-p platform-file)
(load platform-file))))
(load-platform)
(defvar *pkg* nil)
(defun lp ()

View File

@ -21,4 +21,4 @@
(defun add-to-package (filename list)
(with-sd-card (str filename 1)
(dolist (f lst)
(symbol-def f str))))
(symdef str))))

View File

@ -25,6 +25,6 @@ the stream, which follows the 'format directives."
(defun i2c-scan2 (port)
(dotimes (addr 127)
(with-i2c (str port addr)
(format t "~2,0'x: " addr)
(format t "~,20'x: " addr)
(if str (print t)
(print nil)))))

View File

@ -11,7 +11,7 @@
// Compile options
#define resetautorun
// #define printfreespace
#define printfreespace
// #define printgcs
#define sdcardsupport
#define gfxsupport
@ -21,7 +21,7 @@
#define vt100
#define extensions
#define CPI_PICOCALC 1
#define PLATFORM_PICOCALC 1
#define i2ckbd
#define BAUDRATE 96
@ -39,7 +39,7 @@
defined(ARDUINO_RASPBERRY_PI_PICO_W) || \
defined(ARDUINO_RASPBERRY_PI_PICO_2)
#define RASPBERRY_PI_PICO_PLATFORM
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
#define IS_PICOCALC
#endif
#endif
@ -245,7 +245,7 @@
#define CPU_RP2040
#if defined(gfxsupport)
#include <TFT_eSPI.h> // Hardware-specific library
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
#include <PCKeyboard.h>
PCKeyboard pc_kbd;
TFT_eSPI tft = TFT_eSPI(320,320);
@ -318,7 +318,7 @@
#define CPU_RP2350j
#if defined(gfxsupport)
#include <TFT_eSPI.h> // Hardware-specific library
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
#include <PCKeyboard.h>
PCKeyboard pc_kbd;
TFT_eSPI tft = TFT_eSPI(320,320);
@ -1575,7 +1575,7 @@ saveimage(object *arg)
#if defined(sdcardsupport)
unsigned int imagesize = compactimage(&arg);
#if defined(RASPBERRY_PI_PICO_PLATFORM)
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
if(!SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI)){
error2(PSTR("failed to init SD card"));
@ -1728,7 +1728,7 @@ loadimage(object *arg)
{
#if defined(sdcardsupport)
#if defined(RASPBERRY_PI_PICO_PLATFORM)
#if defined(CPI_PICOCALC)
#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;
@ -1743,11 +1743,16 @@ loadimage(object *arg)
File file;
if (stringp(arg)) {
char buffer[BUFFERSIZE];
file = SD.open(MakeFilename(arg, buffer));
if (!file) {
error2("problem loading from SD card or invalid filename");
}
} else if (arg == NULL) {
if (!SD.exists("/ULISP.IMG")) {
error2("workspace image not found");
}
file = SD.open("/ULISP.IMG");
if (!file) {
error2("problem loading from SD card");
@ -1868,7 +1873,7 @@ autorunimage()
{
#if defined(sdcardsupport)
#if defined(RASPBERRY_PI_PICO_PLATFORM)
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
if(!SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI)){
error2(PSTR("failed to init SD card"));
return;
@ -3587,7 +3592,7 @@ void serialbegin (int address, int baud) {
if (address == 1) Serial1.begin((long)baud*100);
else if (address == 2) Serial2.begin((long)baud*100);
#elif defined(ULISP_SERIAL1)
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
// Waveshare uses Serial1 for default.
if (address == 1) {}
#else
@ -3609,7 +3614,7 @@ void serialend (int address) {
if (address == 1) {Serial1.flush(); Serial1.end(); }
else if (address == 2) {Serial2.flush(); Serial2.end(); }
#elif defined(ULISP_SERIAL1)
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
if (address == 1) {Serial1.flush();}
#else
if (address == 1) {Serial1.flush(); Serial1.end(); }
@ -4706,7 +4711,7 @@ object *sp_withsdcard (object *args, object *env) {
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(CPI_PICOCALC)
#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;
@ -7837,30 +7842,6 @@ object *fn_invertdisplay (object *args, object *env) {
return nil;
}
char getKey () {
char temp;
if (pc_kbd.keyCount() > 0) {
do {
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);
}
}
} while ((temp == 0) || (temp ==255));
if (temp == '@') temp = '~';
if (temp == '_') temp = '\\';
}
return temp;
}
object *fn_getkey (object *args, object *env) {
(void) env, (void) args;
return character(getKey());
}
// Built-in symbol names
const char string0[] = "nil";
const char string1[] = "t";
@ -8111,7 +8092,6 @@ const char string245[] = "invert-display";
const char string246[] = ":led-builtin";
const char string247[] = ":high";
const char string248[] = ":low";
const char string262[] = "get-key";
#if defined(CPU_ATSAMD21)
const char string249[] = ":input";
const char string250[] = ":input-pullup";
@ -8864,8 +8844,6 @@ 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 doc262[] = "(get-key)\n"
"Get the next key from the keyboard.";
// Built-in symbol lookup table
const tbl_entry_t lookup_table[] = {
@ -9118,7 +9096,6 @@ const tbl_entry_t lookup_table[] = {
{ string246, (fn_ptr_type)LED_BUILTIN, 0, NULL },
{ string247, (fn_ptr_type)HIGH, DIGITALWRITE, NULL },
{ string248, (fn_ptr_type)LOW, DIGITALWRITE, NULL },
{ string262, fn_getkey, 0200, doc262 },
#if defined(CPU_ATSAMD21)
{ string249, (fn_ptr_type)INPUT, PINMODE, NULL },
{ string250, (fn_ptr_type)INPUT_PULLUP, PINMODE, NULL },
@ -10474,7 +10451,7 @@ initgfx()
digitalWrite(34, HIGH);
#elif defined(RASPBERRY_PI_PICO_PLATFORM)
tft.init();
#if defined(CPI_PICOCALC)
#if defined(PLATFORM_PICOCALC)
tft.setRotation(0);
tft.invertDisplay(1);
#endif
@ -10505,7 +10482,7 @@ void setup () {
}
#if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2W)
#if defined(sdcardsupport) && defined(CPI_PICOCALC)
#if defined(sdcardsupport) && defined(PLATFORM_PICOCALC)
// picocalc doesn't have touch screen
pinMode(SDCARD_SS_PIN,OUTPUT);
digitalWrite(SDCARD_SS_PIN,1);
@ -10521,7 +10498,6 @@ void setup () {
initkybd();
#endif
pfstring(PSTR("uLisp 4.7b "), pserial); pln(pserial);
loadimage(NULL);
}
// Read/Evaluate/Print loop

View File

@ -22,7 +22,61 @@ bcd_to_dec(uint8_t n)
return ((n>>4) * 10) + (n&0x0f);
}
// Definitions
/*
* 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<uint8_t>(n));
return number(static_cast<int>(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<uint8_t>(n));
return number(static_cast<int>(result));
}
object *
fn_now(object *args, object *env)
{
@ -130,6 +184,27 @@ fn_sym_def(object *args, object *env)
return bsymbol(NOTHING);
}
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)
{
@ -146,35 +221,190 @@ fn_lambdap(object *arg, object *env)
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_backlight(object *args, object *env)
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 (arg != nil) {
if (!(floatp(arg))) {
error2(notanumber);
}
pc_kbd.setBacklight(arg->single_float);
if (!SD.exists(MakeFilename(arg, buffer))) {
return nil;
}
float level = pc_kbd.backlight();
return tee;
}
return makefloat(level);
/*
(sd-make-dir path)
Create a directory on the SD card.
This will also create any intermediate directories that dont 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;
}
// Symbol names
const char stringlambdap[] PROGMEM = "lambdap";
const char stringnow[] PROGMEM = "now";
const char string_sym_def[] PROGMEM = "symbol-def";
const char string_backlight[] PROGMEM = "backlight";
/*
(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;
// Documentation strings
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;
char *sd_path_buf = NULL;
SDBegin();
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
/*
* 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";
#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
/*
* 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.";
@ -183,18 +413,46 @@ 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 docpform[] PROGMEM = "(pform form str)\n"
"Print a form to a stream in a manner suitable for writing to storage.";
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_backlight[] PROGMEM = "(backlight level)\n"
"If level is nil, return the current backlight level. Otherwise, set"
"the backlight to the level. Returns the current backlight level.";
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.";
#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
// Symbol lookup table
@ -202,7 +460,19 @@ 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 },
{ string_backlight, fn_backlight, 0201, doc_backlight },
{ 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 },
#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
};
// Table cross-reference functions