QNICE-FPGA icon indicating copy to clipboard operation
QNICE-FPGA copied to clipboard

CR/LF might not work on terminals with 1 Mbit/s baudrate

Open sy2002 opened this issue 3 years ago • 3 comments

IO$GETS_CORE in monitor/io_library.asm implements the various gets variants that are used throughout the whole system. For providing maximum flexibility regarding the end user's terminal settings, the Monitor accepts as line ends: CR or LF or CR/LF. For being able to do the latter one, a timed wait is being used, see this comment from the source code:

                ; For also accepting CR/LF, we need to do a non-blocking
                ; check on STDIN, if there is another character waiting.
                ; IO$GETCHAR is a blocking call, so we cannot use it here.
                ; STDIN = UART, if bit #0 of IO$SWITCH_REG = 0, otherwise
                ; STDIN = PS/2 ("USB") keyboard
                ;
                ; At a terminal speed of 115200 baud = 14.400 chars/sec
                ; (for being save, let us assume only 5.000 chars/sec)
                ; and a CPU frequency of 50 MHz we need to wait about
                ; 10.000 CPU cycles until we check, if the terminal program
                ; did send one other character. The loop at GETS_CR_WAIT
                ; costs about 7 cycles per iteration, so we loop (rounded up)
                ; 2.000 times.
                ; As a simplification, we assume the same waiting time
                ; for a PS/2 ("USB") keyboard

_IO$GETS_CR     MOVE    2000, R3            ; CPU speed vs. transmit speed
_IO$GETS_CRWAIT SUB     1, R3
                RBRA    _IO$GETS_CRWAIT, !Z

Challenge:

CR (stand alone) as a line end and LF (stand alone) as a line end should always work fine.

But CR/LF is probably not stable on terminals with 1 Mbit/s baudrate.

Back in the days, when there was no support for switchable baudrates, this hardcoded solution seemed to be good enough.

Solution:

  • Refactor this and take the baudrate divisor into consideration.
  • Use the to-be-done delay OS function as described in issue #189 for being accurate and flexibe.
  • Make sure not to use any magic numbers but only constants from our global constants file

sy2002 avatar Dec 06 '20 03:12 sy2002

Without having thought about this issue in depth, couldn't we set a flag when we encounter a LF character and just return from the routine. Upon the next GETx we check if the first character read is CR. If true and if the flag is set, we just discard the CR character. In either case we reset the flag after reading the first character. Would this work?

bernd-ulmann avatar Dec 06 '20 12:12 bernd-ulmann

@bernd-ulmann Great idea! And so much simpler and more stable than using a delay. 👍

In the meantime we do have a hardware FIFO in the FPGA UART implementation, so this would work even if the program at hand is not calling GETx in a loop but only from time to time: The surplus LF(*) would just sit in the FIFO and do no harm.

P.S. About (*): I guess you mixed things a bit and wanted to say: [For being able to support CR/LF additionally to a pure CR or a pure LF]: "we set a flag when we enocunter a CR and just return from the routine. Upon the next GETx we check if the first character read is LF. If true and if the flag is set, we just discard the LF character. In either case we reset the flag after reading the first character."

sy2002 avatar Dec 07 '20 08:12 sy2002

You are, of course, right... The CR should set the flag and then suppress an optional LF coming afterwards. :-)

bernd-ulmann avatar Dec 07 '20 09:12 bernd-ulmann