Suspend to SD-card on power button


#1

To make it easier to save and resume work, I’ve implemented a simple suspend-to-SD-card trigger using the uLisp’s save-image functionality, in connection with the PicoCalc BIOS 1.4 soft power button function.

When you press the power button on the PicoCalc briefly, it will now cause uLisp to save the current workspace to the SD card into ULISP.IMG. This feature works best in combination with resetautorun, which will automatically load that image back into the workspace on startup. It will then power down.

Holding down the power button for ~2 seconds will still power off the PicoCalc immediately and without saving.

Code changes:

  1. If you haven’t already, uncomment #define resetautorun. Additionally, you need to change a code block in void autorunimage (). Otherwise, resetautorun won’t load the image unless it defines and autorun function, which we don’t do here. Replace these lines
  if (autorun != NULL) {
    loadimage(NULL);
    apply(autorun, NULL, NULL);
  }

by

  loadimage(NULL);
  if (autorun != NULL) {
    apply(autorun, NULL, NULL);
  }
  1. Find where it defines const int KEY_ESC = 0xB1;, and add a new line below with const int KEY_POWER = 0x91;
  2. Find the line enum flag { PRINTREADABLY, RETURNFLAG, ESCAPE, EXITEDITOR, LIBRARYLOADED, NOESC, NOECHO, MUFFLEERRORS, BACKTRACE }; and add an additional flag PWRDOWN: enum flag { PRINTREADABLY, RETURNFLAG, ESCAPE, EXITEDITOR, LIBRARYLOADED, NOESC, NOECHO, MUFFLEERRORS, BACKTRACE, PWRDOWN };
  3. Add two new functions anywhere in the file:
void powerOff () {
  // Send a signal to the keyboard controller to power off the PicoCalc.
  pc_kbd.writeRegister(0x0e, 1);
}

/*
  suspend - write the current memory to non-volatile memory and power down.
*/
void suspend () {
  pfl(pserial); pfstring("Saving image... ", pserial);
  saveimage(NULL);
  pfstring(" done", pserial);
  pfl(pserial); pfstring("Powering down...", pserial);
  powerOff();
  doze(10);
  // If we're still running here, then the power off must have failed?
}
  1. In ProcessKey, find the line if (c == KEY_ESC) { setflag(ESCAPE); return; } and add the following new line after it: if (c == KEY_POWER) { setflag(PWRDOWN); errorend(); } // Power button. Return to REPL and initate power down.
  2. At the beginning of the void repl (object *env) { function, before the for (;;) { line, add the following code:
  if (tstflag(PWRDOWN)) {
    clrflag(PWRDOWN);
    suspend();
  }

Limitations:

  • This won’t store the state of a running program - pressing the power button will jump back to the main REPL (similar to when you press the Esc key), and only then store the current workspace. However, defined variables and functions will be maintained.
  • Requires PicoCalc Keyboard BIOS 1.4 to work. Please see the PicoCalc Wiki for instructions on how to update it.
  • For some reason, the 1.4 keyboard controller BIOS has a delay of 6 seconds after receiving the power-down signal before it actually powers down the PicoCalc. So it will take a few seconds after printing “Powering down…” before actually turning off. I’m not sure yet how to avoid that.
  • There’s no built-in functionality to reset the image and clear the workspace. The easiest way to start fresh is to take the SD card out, then power on the PicoCalc. It will print an error that it couldn’t load the autorun image, which you can ignore. The next time you do the soft power off or run (save-image) (after putting the SD card back in) it will write a new image.

#2

One addition about this part

There’s no built-in functionality to reset the image and clear the workspace

Another simple way to clear the workspace is (mapc makunbound (globals))