1000 lines
22 KiB
C++
1000 lines
22 KiB
C++
/*
|
||
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);
|
||
}
|
||
|
||
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;
|
||
|
||
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
|
||
|
||
|
||
/*
|
||
* 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";
|
||
const char stringSearchStr[] PROGMEM = "search-str";
|
||
const char stringsearchn[] PROGMEM = "searchn";
|
||
|
||
#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];
|
||
}
|