/* User Extensions */ // 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); } // Definitions 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_lambdap(object *arg, object *env) { (void) env; if (consp(arg)) { arg = car(arg); } if (builtin(arg->name) == LAMBDA) { return tee; } return nil; } object * fn_backlight(object *args, object *env) { (void) env; object *arg = car(args); if (arg != nil) { if (!(floatp(arg))) { error2(notanumber); } pc_kbd.setBacklight(arg->single_float); } float level = pc_kbd.backlight(); return makefloat(level); } // 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"; // Documentation strings 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 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."; // 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 }, { string_backlight, fn_backlight, 0201, doc_backlight }, }; // 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]; }