Thanks a lot for stepping in, David. I’ll do my very best.
The uLisp version in question is 4.5. The whole thing revolves around the Teensy USB host keyboard library that hooks up interrupt service routines to detect a key press and release.
First, I added global variables to the section “Global variables”:
bool kb_pressed = false;
bool kb_released = false;
These global variable get set within tiny ISRs added to the main uLisp file:
void on_press () {
kb_released = false;
kb_pressed = true;
}
void on_release () {
kb_pressed = false;
kb_released = true;
}
These ISRs are hooked to the Teensy keyboard driver:
keyboard.attachPress(on_press);
keyboard.attachRelease(on_release);
(“keyboard” is the USB host keyboard object defined and initialized before.)
So far, so good - this mechanism drives my LispBox internal REPL mechanism without flaws: Anytime the driver is questioned for the key last released “kb_released” is tested - if true a new key has been pressed (and released) and can be processed. This is necessary because for some reason the keyboard driver library does not seem to offer “flushing” the variable that contains the key pressed and released last; it’s constantly filled with the last value. That probably makes sense in some way - anyhow, I need to detect when a new key has been pressed. Internally (i.e. within the main uLisp REPL mechanism) this works fine.
Now I want to provide a new uLisp command that allows to poll the USB keyboard from within a Lisp program. So I added it to the extension file like this:
/*
(keyboard-get-key [on_press])
Get key last recognized [when pressed] (default: when released).
*/
object *fn_KeyboardGetKey (object *args, object *env) {
(void) env;
bool check_press = false;
if (args != NULL) {
check_press = (first(args) == nil) ? false : true;
}
if (!check_press) {
if (kb_released) {
kb_released = false;
char temp = translate_key(keyboard.getKey(), keyboard.getModifiers());
if ((temp != 0) && (temp !=255)) {
return number(temp);
}
return nil;
}
}
else {
if (kb_pressed) {
kb_pressed = false;
char temp = translate_key(keyboard.getKey(), keyboard.getModifiers());
if ((temp != 0) && (temp !=255)) {
return number(temp);
}
return nil;
}
}
}
(This function would allow to check whether a key has been pressed or released, but that is of minor importance here.)
As you can see, the function only returns a key value when the global variable “kb_released” has been set and resets it immediately to indicate the key value has been retrieved. When I print the variable’s value to Serial immediately after clearing it, it does have the value “false” - but when I call the Lisp command again without having pressed a new key, the same value is read and retrieved again - somehow “kb_released” has magically become “true” again. The keyboard driver is innocent, I checked that the ISR really is called and serviced when and only when a new key gets pressed.
Maybe I should note that the internal REPL mechanism using the keyboard remains active as well, but theoretically this should have no impact as long as the Lisp program is running and does not access the interactive REPL, I guess. The thing here is: Even when I retrieve a key using my new command from the external Serial connection (thus bypassing the internal REPL, no new USB key is pressed) it should deliver the last value once and only once because the indicator is reset deliberately. Instead, it delivers the same value over and over again until a new key was pressed. The value of the global variable is always “true” when entering the command function, no matter how often it gets set to “false” within afterwards.
I hope I haven’t overlooked something obvious, but I’ve tried very hard to check everything again and again. Thanks a lot for your help!