Interrupt on keypress mode

This commit is contained in:
Anachronaut
2026-08-17 16:02:44 -04:00
parent 91c9d49d1b
commit 08624925fe
11 changed files with 365 additions and 18 deletions
@@ -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
+7 -2
View File
@@ -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