Browse Source

stdio: add stdioReadC

A routine to conveniently read lines from TTY. Extracted from
shell. Will be used in other places.
pull/10/head
Virgil Dupras 5 years ago
parent
commit
e01ee170cb
2 changed files with 114 additions and 81 deletions
  1. +6
    -78
      kernel/shell.asm
  2. +108
    -3
      kernel/stdio.asm

+ 6
- 78
kernel/shell.asm View File

@@ -35,10 +35,6 @@
; number of entries in shellCmdTbl
.equ SHELL_CMD_COUNT 6+SHELL_EXTRA_CMD_COUNT

; Size of the shell command buffer. If a typed command reaches this size, the
; command is flushed immediately (same as pressing return).
.equ SHELL_BUFSIZE 0x20

; *** VARIABLES ***
; Memory address that the shell is currently "pointing at" for peek, load, call
; operations. Set with mptr.
@@ -48,13 +44,8 @@
; written to after parsing.
.equ SHELL_CMD_ARGS SHELL_MEM_PTR+2

; Command buffer. We read types chars into this buffer until return is pressed
; This buffer is null-terminated and we don't keep an index around: we look
; for the null-termination every time we write to it. Simpler that way.
.equ SHELL_BUF SHELL_CMD_ARGS+PARSE_ARG_MAXCOUNT

; Pointer to a hook to call when a cmd name isn't found
.equ SHELL_CMDHOOK SHELL_BUF+SHELL_BUFSIZE
.equ SHELL_CMDHOOK SHELL_CMD_ARGS+PARSE_ARG_MAXCOUNT

; Pointer to a routine to call at each shell loop interation
.equ SHELL_LOOPHOOK SHELL_CMDHOOK+2
@@ -65,14 +56,13 @@ shellInit:
xor a
ld (SHELL_MEM_PTR), a
ld (SHELL_MEM_PTR+1), a
ld (SHELL_BUF), a
ld hl, noop
ld (SHELL_CMDHOOK), hl
ld (SHELL_LOOPHOOK), hl

; print welcome
ld hl, .welcome
jp printstr ; returns
jp printstr

.welcome:
.db "Collapse OS", ASCII_CR, ASCII_LF, "> ", 0
@@ -84,52 +74,12 @@ shellLoop:
ld ix, (SHELL_LOOPHOOK)
call callIX
; Then, let's wait until something is typed.
call stdioGetC
jr nz, shellLoop ; nothing typed? loop
; got it. Now, is it a CR or LF?
cp ASCII_CR
jr z, .do ; char is CR? do!
cp ASCII_LF
jr z, .do ; char is LF? do!
cp ASCII_DEL
jr z, .delchr
cp ASCII_BS
jr z, .delchr

; Echo the received character right away so that we see what we type
call stdioPutC

; Ok, gotta add it do the buffer
; save char for later
ex af, af'
ld hl, SHELL_BUF
xor a ; look for null
call findchar ; HL points to where we need to write
; A is the number of chars in the buf
cp SHELL_BUFSIZE-1 ; -1 is because we always want to keep our
; last char at zero.
jr z, .do ; end of buffer reached? buffer is full. do!

; bring the char back in A
ex af, af'
; Buffer not full, not CR or LF. Let's put that char in our buffer and
; read again.
ld (hl), a
; Now, write a zero to the next byte to properly terminate our string.
inc hl
xor a
ld (hl), a

jr shellLoop

.do:
call stdioReadC
jr nz, shellLoop ; not done? loop
; We're done. Process line.
call printcrlf
ld hl, SHELL_BUF
call stdioGetLine
call shellParse
; empty our buffer by writing a zero to its first char
xor a
ld (hl), a

ld hl, .prompt
call printstr
jr shellLoop
@@ -137,28 +87,6 @@ shellLoop:
.prompt:
.db "> ", 0

.delchr:
ld hl, SHELL_BUF
ld a, (hl)
or a ; cp 0
jr z, shellLoop ; buffer empty? nothing to do
; buffer not empty, let's delete
xor a ; look for null
call findchar ; HL points to end of buf
dec hl ; the char before it
xor a
ld (hl), a ; set to zero
; Char deleted in buffer, now send BS + space + BS for the terminal
; to clear its previous char
ld a, ASCII_BS
call stdioPutC
ld a, ' '
call stdioPutC
ld a, ASCII_BS
call stdioPutC
jr shellLoop


; Parse command (null terminated) at HL and calls it
shellParse:
push af


+ 108
- 3
kernel/stdio.asm View File

@@ -1,20 +1,36 @@
; stdio
;
; Allows other modules to print to "standard out", and get data from "stamdard
; Allows other modules to print to "standard out", and get data from "standard
; in", that is, the console through which the user is connected in a decoupled
; manner.
;
; *** VARIABLES ***
; *** Consts ***
; Size of the readline buffer. If a typed line reaches this size, the line is
; flushed immediately (same as pressing return).
.equ STDIO_BUFSIZE 0x20

; *** Variables ***
; Used to store formatted hex values just before printing it.
.equ STDIO_HEX_FMT STDIO_RAMSTART
.equ STDIO_GETC STDIO_HEX_FMT+2
.equ STDIO_PUTC STDIO_GETC+2
.equ STDIO_RAMEND STDIO_PUTC+2

; Line buffer. We read types chars into this buffer until return is pressed
; This buffer is null-terminated and we don't keep an index around: we look
; for the null-termination every time we write to it. Simpler that way.
.equ STDIO_BUF STDIO_PUTC+2

; Index where the next char will go in stdioGetC.
.equ STDIO_BUFIDX STDIO_BUF+STDIO_BUFSIZE
.equ STDIO_RAMEND STDIO_BUFIDX+1

; Sets GetC to the routine where HL points to and PutC to DE.
stdioInit:
ld (STDIO_GETC), hl
ld (STDIO_PUTC), de
xor a
ld (STDIO_BUF), a
ld (STDIO_BUFIDX), a
ret

stdioGetC:
@@ -88,3 +104,92 @@ printHexPair:
call printHex
pop af
ret

; Call stdioGetC and put the result in the buffer. Sets Z according to whether
; the buffer is "complete", that is, whether CR or LF have been pressed or if
; the the buffer is full. Z is set if the line is "complete", unset if not.
; The next call to stdioReadC after a completed line will start a new line.
;
; This routine also takes care of echoing received characters back to the TTY.
;
; Note that this routine doesn't bother returning the typed character.
stdioReadC:
; Let's wait until something is typed.
call stdioGetC
jr nz, stdioReadC ; nothing typed? loop
; got it. Now, is it a CR or LF?
cp ASCII_CR
jr z, .complete ; char is CR? buffer complete!
cp ASCII_LF
jr z, .complete
cp ASCII_DEL
jr z, .delchr
cp ASCII_BS
jr z, .delchr

; Echo the received character right away so that we see what we type
call stdioPutC

; Ok, gotta add it do the buffer
; save char for later
ex af, af'
ld a, (STDIO_BUFIDX)
push hl ;<|
ld hl, STDIO_BUF ; |
; make HL point to dest spot |
call addHL ; |
; Write our char down |
ex af, af' ; |
ld (hl), a ; |
; follow up with a null char |
inc hl ; |
xor a ; |
ld (hl), a ; |
pop hl ;<|
; inc idx, which still is in AF'
ex af, af'
inc a
cp STDIO_BUFSIZE-1 ; -1 is because we always want to keep our
; last char at zero.
jr z, .complete ; end of buffer reached? buffer is full.

; not complete. save idx back
ld (STDIO_BUFIDX), a
; Z already unset
ret

.complete:
; The line in our buffer is complete.
xor a ; sets Z
ld (STDIO_BUFIDX), a
ret

.delchr:
ld a, (STDIO_BUFIDX)
or a
jp z, unsetZ ; buf empty? nothing to do
; buffer not empty, let's go back one char and set a null char there.
dec a
ld (STDIO_BUFIDX), a
push hl ;<|
ld hl, STDIO_BUF ; |
; make HL point to dest spot |
call addHL ; |
xor a ; |
ld (hl), a ; |
pop hl ;<|
; Char deleted in buffer, now send BS + space + BS for the terminal
; to clear its previous char
ld a, ASCII_BS
call stdioPutC
ld a, ' '
call stdioPutC
ld a, ASCII_BS
call stdioPutC
jp unsetZ


; Make HL point to the line buffer. It is always null terminated.
stdioGetLine:
ld hl, STDIO_BUF
ret

Loading…
Cancel
Save