|
- ; shell
- ;
- ; Runs a shell over an asynchronous communication interface adapter (ACIA).
-
- ; Incomplete. For now, this outputs a welcome prompt and then waits for input.
- ; Whenever input is CR or LF, we echo back what we've received and empty the
- ; input buffer. This also happen when the buffer is full.
-
- #include "platform.inc"
-
- ; *** CONSTS ***
- CR .equ 0x0d
- LF .equ 0x0a
-
- ; size of the input buffer. If our input goes over this size, we echo
- ; immediately.
- BUFSIZE .equ 0x20
-
- ; *** VARIABLES ***
- ; Our input buffer starts there
- INPTBUF .equ RAMSTART
-
- ; index, in the buffer, where our next character will go. 0 when the buffer is
- ; empty, BUFSIZE-1 when it's almost full.
- BUFIDX .equ INPTBUF+BUFSIZE
-
- ; *** CODE ***
- jr init
-
- init:
- ; disable interrupts we don't need them
- di
-
- ; setup stack
- ld hl, RAMEND
- ld sp, hl
-
- ; initialize variables
- xor a
- ld (BUFIDX), a ; starts at 0
-
- ; setup ACIA
- ; CR7 (1) - Receive Interrupt disabled
- ; CR6:5 (00) - RTS low, transmit interrupt disabled.
- ; CR4:2 (101) - 8 bits + 1 stop bit
- ; CR1:0 (10) - Counter divide: 64
- ld a, 0b00010110
- out (ACIA_CTL), a
-
- ; print prompt
- ld hl, d_welcome
- call printstr
- call printcrlf
-
- mainloop:
- call readc
- call chkbuf
- jr mainloop
-
- ; spits character in A in port SER_OUT
- printc:
- push af
- .stwait:
- in a, (ACIA_CTL) ; get status byte from SER
- bit 1, a ; are we still transmitting?
- jr z, .stwait ; if yes, wait until we aren't
- pop af
- out (ACIA_IO), a ; push current char
- ret
-
- ; print null-terminated string pointed to by HL
- printstr:
- ld a, (hl) ; load character to send
- or a ; is it zero?
- ret z ; if yes, we're finished
- call printc
- inc hl
- jr printstr
- ; no ret because our only way out is ret z above
-
- printcrlf:
- ld a, CR
- call printc
- ld a, LF
- call printc
- ret
-
- ; wait until a char is read in the ACIA and put it in the read buffer
- readc:
- ; first thing first: is our input buffer full? If yes, we don't even
- ; bother reading the ACIA. Something is wrong: we don't process data
- ; fast enough.
- ld a, (BUFIDX)
- cp BUFSIZE
- ret z ; if BUFIDX == BUFSIZE, our buffer is full.
-
- call getbufptr
-
- ; increase our buf ptr while we still have it in A
- inc a
- ld (BUFIDX), a
-
- .loop:
- ; Read our character from ACIA into our BUFIDX
- in a, (ACIA_CTL)
- bit 0, a ; is our ACIA rcv buffer full?
- jr z, .loop ; no? loop
-
- in a, (ACIA_IO)
- ld (hl), a
-
- ret
-
- ; check if the input buffer is full or ends in CR or LF. If it does, prints it
- ; back and empty it.
- chkbuf:
- ld a, (BUFIDX)
- cp 0
- ret z ; BUFIDX is zero? nothing to check.
-
- cp BUFSIZE
- jr z, .do ; if BUFIDX == BUFSIZE? do!
-
- call getbufptr
- ; our previous char is in BUFIDX - 1. Fetch this
- dec hl
- ld a, (hl) ; now, that's our char we have in A
- inc hl ; put HL back where it was
-
- cp CR
- jr z, .do ; char is CR? do!
- cp LF
- jr z, .do ; char is LF? do!
-
- ; nothing matched? don't do anything
- ret
-
- .do:
- ; terminate our string with 0
- xor a
- ld (hl), a
- ; reset buffer index
- ld (BUFIDX), a
-
- ; alright, let's go!
- ld hl, INPTBUF
- call printstr
- call printcrlf
- ret
-
- ; Set current buffer pointer in HL. The buffer pointer is where our *next* char
- ; will be written.
- getbufptr:
- ld hl, INPTBUF
- xor b
- ld c, a
- add hl, bc ; hl now points to INPTBUF + BUFIDX
- ret
-
- ; *** DATA ***
- d_welcome: .byte "Welcome to Collapse OS", 0
|