KybdAvailable not always cleared as expected


#1

(I seriously doubt this is truly a bug, but I guess I picked this category anyway.)

I’m using read-line to get a string of input from the terminal. But it’s returning a value even though I haven’t typed anything yet.

It seems that when gserial is called from fn_readline (or rather from gstreamfun, which was called by fn_readline) (with lineeditor compile option enabled) the KybdAvailable variable is still set to 1 (it wasn’t set to 0 after returning the final character from the last line I entered… apparently??). I can’t explain why I don’t run into this problem in the REPL.

I changed this behavior by setting a global variable (flag) in the fn_readline function and using that flag in gserial to set KybdAvailable to 0, forcing gserial to wait until I actually type something. Since this is triggered by something in the fn_readine function, it has no impact on the REPL.

I probably won’t want to leave it like that. This is only necessary when the Stream is Serial.

I forked uLisp in order to output to Serial1 (which is straightforward) and to use a USB Keyboard connected to a Teensy 4.1 (though the serial port continues to be used as an input source). So it’s no big deal to make a minor change but I thought I would mention it here in case it rings any bells.

In case you want to see the code… My version of gserial is pretty different but I’m talking about the teensykeyClearKbdBuff reference beginning on line 11 of this code snippet. If teensykeyClearKbdBuff is true (having been set to true in fn_readline), KybdAvailable and WritePtr are set to 0 and teensykeyClearKbdBuff is set to false.

int gserial () {
  bool charAvailable=false;
  char temp=0;
  if (LastChar) {
    temp = LastChar;
    LastChar = 0;
    return temp;
  }
#if defined(lineeditor)
#ifdef teensyusbhostkb
  if(teensykeyClearKbdBuff){
    KybdAvailable=0;
    WritePtr=0;
    teensykeyClearKbdBuff=false;
  }
#endif
  
while (!KybdAvailable) {
  charAvailable=false;
  while (!charAvailable){
    if(Serial.available()){
      temp = Serial.read();
      charAvailable=true;
    }
#if defined teensyusbhostkb
  else{
    if(teensykeyAvailable){
      temp=teensykey;
      teensykeyAvailable=false;
      charAvailable=true;
    }
  }
#endif      
}
processkey(temp);
  }
  if (ReadPtr != WritePtr) return KybdBuf[ReadPtr++];
  KybdAvailable = 0;
  WritePtr = 0;
  return '\n';

#2

Thanks for reporting this. The read-line function definitely shouldn’t return until you enter a return character, so it is a bug.

Does it only happen with the lineeditor compile option enabled?

Thanks, David


#3

That last post was unnecessarily complicated. Sorry for that. I’ve now done what I should have done in the first place, flash unmodified uLisp for ARM to something and test it to confirm the behavior isn’t because of something I did.

So I flashed it to a Raspberry Pi Pico, assuming the compile option differences between the Pico and Teensy aren’t a factor…

Without lineeditor compiler option…

uLisp 4.0
15487> (defvar q)
q

15484> (setq q (read-line))
line 1

After I entered (setq q (read-line)), I typed in the “line 1” text. Then, I’m stuck entering text into the same line forever. Typing Enter only moves the cursor to the beginning of the line.

With lineeditor compiler option…

uLisp 4.0 
15487> (defvar q)
q

15484> (setq q (read-line))                                                     
""         

After I enter (setq q (read-line)), SETQ responds with an empty string (presumably).

This is the same behavior I see in my modified version of uLisp (prior to my clumsy fix described in my original post).


#4

Thanks for the additional information. How are you interacting with uLisp? Via the Serial Monitor described here: Using uLisp, or via a terminal described here: Using uLisp from a terminal?


#5

I’m using minicom to connect to the pico. Thanks for looking into this!


#6

Without the lineeditor compiler option it works if you terminate the entry by typing Ctrl-J (linefeed) rather than return. This is because uLisp follows the Lisp convention of using the linefeed character as a line terminator. Perhaps I should allow return to terminate (read-line) too.

I’ll investigate with the lineeditor compiler option.

David


#7

Thanks for telling me about CTRL-J and Lisp’s EOL convention. That connects a couple of lonely dots.