Interrupt on keypress mode
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
; Tests interrupt on input: the console asking for attention instead of being asked.
|
||||
;
|
||||
; The control port has two bits and they are independent of one another. Bit 0 puts the
|
||||
; console in key mode; bit 1 says to put the interrupt line up when a byte arrives. The
|
||||
; console is on port 0x00, so that is the vector a key comes through - a device raises its
|
||||
; line on its base port, and the status and control ports belong to the same device as the
|
||||
; data port.
|
||||
;
|
||||
; The main program does nothing at all but wait to be told it is finished. It never looks
|
||||
; at the console, which is the whole point: every byte is dealt with by the handler.
|
||||
;
|
||||
; What the status bits mean:
|
||||
; bit 0 READY reading the data port will not have to wait
|
||||
; bit 1 ENDED input has run out for good
|
||||
; bit 2 KEYMODE the console is in key mode
|
||||
; bit 3 INTERRUPTS the console is set to raise its line when a byte arrives
|
||||
;
|
||||
; This runs with input from a file rather than a terminal, so key mode has no terminal to
|
||||
; put into another state and nothing here depends on one. A pipe with bytes in it is a
|
||||
; console with keys waiting as far as the console is concerned.
|
||||
|
||||
#Include console.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
CIF ; Nothing gets through until there is something to catch it.
|
||||
|
||||
SETD.0 Banner
|
||||
CALL printString
|
||||
CALL newLine
|
||||
|
||||
; Key mode and interrupt on input, asked for in one write. Neither bit depends on the
|
||||
; other, so there is no order to get wrong.
|
||||
INIA 0x03
|
||||
OUTA 0x02
|
||||
SETD.0 AskedLabel
|
||||
CALL printString
|
||||
CALL showStatus
|
||||
|
||||
SETD.0 ArrivedLabel
|
||||
CALL printString
|
||||
CALL newLine
|
||||
|
||||
SIF ; From here a byte arriving runs keyHandler.
|
||||
|
||||
waitLoop:
|
||||
; Waiting without looking. Nothing in this loop touches the console, so every byte that
|
||||
; comes out below was put there by something that interrupted this.
|
||||
SETD.3 Finished
|
||||
LDA.3
|
||||
RSTB
|
||||
OR ; Q is the flag, so this is a test for zero.
|
||||
BRQ waitLoop
|
||||
|
||||
CALL newLine
|
||||
RSTA
|
||||
OUTA 0x02 ; Line mode and no interrupts, the way it was found.
|
||||
SETD.0 DoneLabel
|
||||
CALL printString
|
||||
CALL showStatus
|
||||
HALT
|
||||
|
||||
; Entered because the console had something to say. It is never called.
|
||||
;
|
||||
; DP3 is used freely here: an interrupt saves all four Data Pointers and RETI puts them
|
||||
; back, so a handler cannot disturb what it interrupted no matter what it touches.
|
||||
keyHandler:
|
||||
INA 0x01
|
||||
INIB 0x02 ; ENDED
|
||||
AND
|
||||
BNQ keyEnded
|
||||
INA 0x00 ; The byte this interrupt was about.
|
||||
OUTA 0x00 ; Nothing echoes in key mode, so the program does it.
|
||||
RETI
|
||||
|
||||
keyEnded:
|
||||
; The end of input raises the line once, so a program driven entirely by interrupts
|
||||
; still finds out that nothing more is coming. Without it this would wait forever for a
|
||||
; key that cannot arrive.
|
||||
SETD.3 Finished
|
||||
INIA 0x01
|
||||
STA.3
|
||||
RETI
|
||||
|
||||
; Prints the status byte as hex and then names the bits that are up, so a change in the
|
||||
; output says which bit moved rather than only that the number is different.
|
||||
showStatus:
|
||||
INA 0x01
|
||||
PSHA
|
||||
CALL printByteHex
|
||||
INIA 0x20
|
||||
OUTA 0x00
|
||||
POPA
|
||||
PSHA
|
||||
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ showNotReady
|
||||
SETD.0 ReadyWord
|
||||
CALL printString
|
||||
showNotReady:
|
||||
POPA
|
||||
PSHA
|
||||
|
||||
INIB 0x02
|
||||
AND
|
||||
BRQ showNotEnded
|
||||
SETD.0 EndedWord
|
||||
CALL printString
|
||||
showNotEnded:
|
||||
POPA
|
||||
PSHA
|
||||
|
||||
INIB 0x04
|
||||
AND
|
||||
BRQ showNotKeys
|
||||
SETD.0 KeysWord
|
||||
CALL printString
|
||||
showNotKeys:
|
||||
POPA
|
||||
|
||||
INIB 0x08
|
||||
AND
|
||||
BRQ showNotInterrupts
|
||||
SETD.0 InterruptsWord
|
||||
CALL printString
|
||||
showNotInterrupts:
|
||||
CALL newLine
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
Banner:
|
||||
"console input interrupts"
|
||||
|
||||
AskedLabel:
|
||||
"asked for: "
|
||||
ArrivedLabel:
|
||||
"what arrived:"
|
||||
DoneLabel:
|
||||
"at the end: "
|
||||
|
||||
ReadyWord:
|
||||
"ready "
|
||||
EndedWord:
|
||||
"ended "
|
||||
KeysWord:
|
||||
"keys "
|
||||
InterruptsWord:
|
||||
"interrupts "
|
||||
|
||||
; Set by the handler when the console says there will be no more bytes. It is the only
|
||||
; thing the handler and the program it interrupts have to say to each other.
|
||||
Finished:
|
||||
0x00
|
||||
|
||||
#Vectors
|
||||
|
||||
Boot start
|
||||
Device 0x00 keyHandler
|
||||
@@ -10,6 +10,10 @@
|
||||
; bit 1 ENDED input has run out for good
|
||||
; bit 2 KEYMODE the console is in key mode
|
||||
;
|
||||
; There is a fourth bit, for whether the console interrupts on input, and nothing here
|
||||
; sets it. Polling and interrupting are the two ways to get a byte and this is the one
|
||||
; about polling; consoleInterruptTest.asm is the other.
|
||||
;
|
||||
; This runs with input from a file rather than a terminal, so key mode has no terminal to
|
||||
; put into another state and the mode bit is the only thing that changes. That is on
|
||||
; purpose: the same program has to work either way, and a test that needed a terminal
|
||||
@@ -60,8 +64,9 @@ readDone:
|
||||
|
||||
; ---- The status at the end of input ----
|
||||
;
|
||||
; READY is set as well as ENDED, because a read does answer at once. It just answers
|
||||
; 0xFF forever. ENDED is what says so.
|
||||
; ENDED is set and READY is clear, although a read would answer at once here: what it
|
||||
; answers is 0xFF standing in for nothing. READY means there is a byte to be had, so the
|
||||
; loop above stops on its own rather than taking imaginary bytes forever.
|
||||
SETD.0 AtEndLabel
|
||||
CALL printString
|
||||
CALL showStatus
|
||||
|
||||
Reference in New Issue
Block a user