Keyboard Input on the
6800, 6801, and 6809
(EXORsim)
Now that we can get both binary and hexadecimal output, including on the 68000, let's get some input.
(I'm itching to move on to multiplication and division, but before we do that we really need to make sure we can get input from the keyboard.)
First, we'll just get a key and output it. Then we'll try something a bit more interesting.
Assuming your framework rigging is in place, lets go look at the BIOS routines again, referring back to the not-yet-on-the-beach example.You'll remember we found a facts file, and we found suspicious labels when looking for an output character routine. Nearby the OUTCH function was an INCH function and an INCHN function. The explanations weren't very clear, but we later dug into the M6809 EXORciser manual and found more information on page 3-33. Even though that's for the 6809, and is not included in the M6800 EXORciser manual, the facts files are the same, so we guess that the functional descriptions are good for the 6800, too.
XINCHN strips a "parity" bit off. That's the high bit that in many terminals of the day would be a parity bit rather than a data bit -- 7 bits of data, 1 bit of parity, stop and start bits, etc. We don't need that.
Then there is XINCH:
XINCH EQU $F012 ; wait for key, return in A, preserves B, X, see AECHO
XINCH waits for a key input and brings it back to us. That ought to be useful. What's AECHO? Maybe we don't need to know. Let's see if we can do something simple, something along the lines of
* Essential monitor ROM routines
XINCH EQU $F012 ; wait for key, return in A, preserves B, X, see AECHO
XOUTCH EQU $F018 ; output ACCM A to debug terminal, preserves B,X
*
ORG $2000
START JSR XINCH
JSR XOUTCH
BRA START
Looks possible. Get a 6800 session of EXORsim going, assemble that, and
see what it does.
$ ./exor --mon
Load facts file 'facts'
'exbug.bin' loaded.
EXBUG-1.1 detected
'mdos.dsk' opened for drive 0 (double sided)
OSLOAD...
Hit Ctrl-C for simulator command line. Starting simulation...
> 0 A=00 B=00 X=0000 SP=00FF ------ 0020: B6 E8 00 LDA E800
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% a 0
0000: * Essential monitor ROM routines
0000: XINCH EQU $F012 ; wait for key, return in A, preserves B, X, see AECHO
0000: XOUTCH EQU $F018 ; output ACCM A to debug terminal, preserves B,X
0000: *
0000: ORG $2000
2000: START JSR XINCH
2003: JSR XOUTCH
2006: BRA START
2008:
%
Step through until we see something?
% s 2000
0 A=00 B=00 X=0000 SP=00FF ------ START 2000: BD F0 12 JSR F012 EA=F012(XINCH)
> 1 A=00 B=00 X=0000 SP=00FD ------ XINCH F012: 7E FA 8B JMP FA8B
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
2 ---- Subroutine at FA8B processed by simulator ---- RTS executed ---
> 3 A=00 B=00 X=0000 SP=00FF ------ 2003: BD F0 18 JSR F018
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
That was sudden. Not sure why it wouldn't let us step through the ROM at FA88.
But I don't see any input or anything, and it didn't seem to wait for a key.
Step some more?
% s
3 A=00 B=00 X=0000 SP=00FF ------ 2003: BD F0 18 JSR F018 EA=F018(XOUTCH)
> 4 A=00 B=00 X=0000 SP=00FD ------ XOUTCH F018: 7E F9 DC JMP F9DC
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
4 A=00 B=00 X=0000 SP=00FD ------ XOUTCH F018: 7E F9 DC JMP F9DC EA=F9DC(OUTCH)
> 5 A=00 B=00 X=0000 SP=00FD ------ OUTCH F9DC: 37 PSHB Output character with NULs
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
5 A=00 B=00 X=0000 SP=00FD ------ OUTCH F9DC: 37 PSHB Output character with NULs
> 6 A=00 B=00 X=0000 SP=00FC ------ F9DD: F6 FC F4 LDB FCF4
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
6 A=00 B=00 X=0000 SP=00FC ------ F9DD: F6 FC F4 LDB FCF4 EA=FCF4(ACIA0) D=03
> 7 A=00 B=03 X=0000 SP=00FC ------ F9E0: C5 02 BITB #02
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
7 A=00 B=03 X=0000 SP=00FC ------ F9E0: C5 02 BITB #02 EA=F9E1 D=02
> 8 A=00 B=03 X=0000 SP=00FC ------ F9E2: 27 F9 BEQ F9DD
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
8 A=00 B=03 X=0000 SP=00FC ------ F9E2: 27 F9 BEQ F9DD EA=F9DD
> 9 A=00 B=03 X=0000 SP=00FC ------ F9E4: B7 FC F5 STA FCF5
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
9 A=00 B=03 X=0000 SP=00FC ------ F9E4: B7 FC F5 STA FCF5 EA=FCF5(ACIA1) D=00
> 10 A=00 B=03 X=0000 SP=00FC ---Z-- F9E7: 81 0D CMPA #0D
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
10 A=00 B=03 X=0000 SP=00FC ---Z-- F9E7: 81 0D CMPA #0D EA=F9E8 D=0D
> 11 A=00 B=03 X=0000 SP=00FC --N--C F9E9: 26 1B BNE FA06
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
11 A=00 B=03 X=0000 SP=00FC --N--C F9E9: 26 1B BNE FA06 EA=FA06
> 12 A=00 B=03 X=0000 SP=00FC --N--C FA06: 7D FF 02 TST FF02
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
12 A=00 B=03 X=0000 SP=00FC --N--C FA06: 7D FF 02 TST FF02 EA=FF02(NULCTRL)
> 13 A=00 B=03 X=0000 SP=00FC ---Z-- FA09: 2A F9 BPL FA04
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
13 A=00 B=03 X=0000 SP=00FC ---Z-- FA09: 2A F9 BPL FA04 EA=FA04
> 14 A=00 B=03 X=0000 SP=00FC ---Z-- FA04: 33 PULB
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s
14 A=00 B=03 X=0000 SP=00FC ---Z-- FA04: 33 PULB
> 15 A=00 B=00 X=0000 SP=00FD ---Z-- FA05: 39 RTS
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
Like me, are you not seeing anything that looks like we got input from the keyboard and put it out?
Let's try just running it from here.
% c
SSAADDKKQQWWEE999900DDLLKKJJAASSDDFFInterrupt!
139572 ---- Subroutine at FA8B processed by simulator ---- RTS executed ---
> 139573 A=00 B=00 X=0000 SP=00FF ---Z-- 2003: BD F0 18 JSR F018
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
Well, that definitely was grabbing keys from the keyboard and putting them out until I hit Ctrl-C.
But twice?
Like an echo?
When working with terminals that take input from the keyboard and send it to a computer, it can be useful to just let the character echo back out to the screen before the computer processes it. Or, at least, back in the 1970s, it could be.
So we read about XINCH again, and then we go looking for AECHO in the 6809
manual, and it looks like
* Essential monitor ROM parameters
* ECHO suppress -- set non-zero before each call to XINCH/XINCHN
* to suppress echo for that call only.
But the facts file says AECHO is
ff53 rmb 1 AECHO Echo flag: 0=echo
where the EXORciser 6809 manual says it's at $FF58.
The facts09 file agrees with the facts file. Which is it?
So I decided to trust the manual first. It says it must be set non-zero before every call to suppress echo. Weird, but I tried it. No effect.
So, among a few other things, I tried the value in the facts file, but setting
it non-zero before every call like the EXORciser 6809 manual says, like
this:
* Essential monitor ROM routines
XINCH EQU $F012 ; wait for key, return in A, preserves B, X, see AECHO
XOUTCH EQU $F018 ; output ACCM A to debug terminal, preserves B,X
*
* Essential monitor ROM parameters
* ECHO suppress -- set non-zero before each call to XINCH/XINCHN
* to suppress echo for that call only.
* Not the same address as 6809 EXBUG09.
AECHO EQU $FF53 ; ECHO suppress per-call
*
ORG $2000
START LDAA #-1
STAA AECHO
JSR XINCH
JSR XOUTCH
BRA START
I pasted that into the assemble command in a 6800 session, and it performed as expected, pretty much. Give it a try.
And while your practicing your typing skills, try Ctrl-H, Ctrl-J, Ctrl-K, and Ctrl-L just for fun.
Trying this code in EXORsim6801's exor command, I discovered that EXORsim 6801's assembler doesn't seem to like -1 for immediates. So I tried 0-1:
START LDAA #0-1
That worked the way it should -- just remember that, when you hit Ctrl-C,
EXORsim is going to throw a long backtrace at you.
On the 6809, I did have to define AECHO according to the manual, to location $FF581:
AECHO EQU $FF58 ; ECHO suppress per-call
And remember LDAA is LDA, and STAA is STA on the 6809.
So I backed up the facts09 file to something named facts09.bk20241024 or something and fixed that line in the facts09 file.
Something to think about, but a load and a store before calling keyboard input seems like a bit of waste motion, maybe? Since XINCH requires that variable to be set before every call, to suppress echo, it must be resetting it after every call.
That means, every time we want to call XINCH, it must have been cleared already.
So if we just INCrement it, or DECrement, or COMplement it, it will be non-zero. And we can two instructions in 5 bytes for one instruction in 3 bytes. Something to think about, right?
Now, we want our input character routine to be compatible with the rest of the
functions in the framework we're building, so we need to define some glue and entry points and test code, starting with the 6800. But this chapter is getting a little long to put the code for all three 8-bit CPUs in.
No comments:
Post a Comment