update to new picocalc release.

This commit is contained in:
Kyle Isom 2025-04-28 21:23:12 -07:00
parent f6c22d170a
commit 86411d214d
4 changed files with 1335 additions and 3714 deletions

22
LICENSE Normal file
View File

@ -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.

View File

@ -13,7 +13,8 @@
** Platforms
*** picocalc:
*** teensy:
*** t-deck
*** builder
+ picocalc
+ teensy
+ t-deck
+ builder

File diff suppressed because it is too large Load Diff

View File

@ -1,994 +0,0 @@
/*
User Extensions
LispBox uLisp Extension - Version 1.0 - June 2024
Hartmut Grawe - github.com/ersatzmoco - June 2024
edited by hasn0life for Lilygo T-Deck - Jan 2025
updated by picolisper for LilyGo T-Deck and
PicoCalc - April 2025
*/
// Utility functions
uint8_t
dec_to_bcd(uint8_t n)
{
uint8_t bcd = 0;
uint8_t tens = n / 10;
bcd = tens << 4;
tens *= 10;
bcd += (n - tens) & 0x0f;
return bcd;
}
uint8_t
bcd_to_dec(uint8_t n)
{
return ((n>>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<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)
{
(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 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;
}
/*
(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];
}