Checking whether a printer is online
The hard way.
Long before we had bidirectional parallel communication and modern printer drivers, and when we did all of our printing in plain text on 9-pin dot matrix printers, checking to see if a printer was switched on and set as online within your code was not so easy. You had to do something like this code fragment from LSAIT Hangman:
2430DEFFNck:LOCALa,t,q:a=1 2440PROCm("Testing for printer..."):OSCLI("FX21,3"):t=ADVAL(-4) 2450OSCLI("FX3,10"):VDU127,127,127:OSCLI("FX3,0"):q=INKEY25:IFADVAL(-4)<t a=0 2460IFa=0PROCm("Oops-printer not ready."):t=INKEY(150) 2470=a
The specifics:
OSCLI("FX21,3"):t=ADVAL(-4)
Flush the printer output buffer, and read the buffer’s capacity. ADVAL()
is designed to read values from the analogue-to-digital converter but with negative arguments will read operating system buffer space.
OSCLI("FX3,10")
Switch the machine to printer output only. Not really sure what this actually does, other than that it works! Neither the Model B nor the B+ manuals are clear. (Forget what I said previously about 2 and 10: the API changed.)
VDU127,127,127
Write three backspace characters; these will only be sent to the printer as that is presently the single active output device.
OSCLI("FX3,0"):q=INKEY25:IFADVAL(-4)<t a=0Set output back to screen only, pause, and re-read the printer buffer capacity. If the capacity has dropped, at least one of those three backspaces is still sat in the buffer, going nowhere. Were the printer online, it would have silently eaten them and the buffer would have returned to empty, so the determined capacity would not appear to have changed. If the capacity has dropped, the printer ain’t ready.
The original code that I “borrowed” for this task omitted the pause and I was puzzled to find it to be rather erratic, until I realised that I needed to pause the program to let the OS deal with the request for printed output.
OSCLI and the Acorn MOS system calls
Under Acorn MOS, OSCLI does indeed stand for Operating System Command Line Interpreter, which is a system call that executes a single command string. Earlier versions of Acorn MOS had no shell, and expected that OS commands would be passed in by the active language or application using the OSCLI system call. Languages and applications that provide a command prompt, for example BBC BASIC and the Acornsoft View word processor, pass any command beginning with “*
” directly to the OS:
*FX 3, 10 *CONFIGURE TUBE *HELP BASIC
In BBC BASIC, a *
indicates that the remainder of the line is an OS command. A BASIC command OSCLI()
exists to invoke OS commands where you want some of the command line to be formed from variables or function output, e.g. OSCLI("FX3, " + outMode%)
. The following instructions are equivalent:
10 *FX 3, 10
10 OSCLI("FX 3, 10")
10 OsCli=&FFF7 :REM change case to avoid conflict with OSCLI() 20 ... 1000 DIM command 8 :REM closest BBC BASIC has to pointers 1010 $command="FX 3, 10" :REM $ operator includes &0D terminator 1020 X%=command MOD 256 :REM X and Y point to address of command line 1030 Y%=command DIV 256 1060 CALL OsCli :REM call the OS to execute the command
A operating system command of the form FX a[, x[, y]]
allows the OSBYTE system call to be made directly from the command line; the three parameters a
, x
and y
are passed into the accumulator and X and Y registers on entry. OSBYTE provides a wide range of services selected using the accumulator, all of which require only one or two bytes of parameters held in X and Y. The following command to direct text output to the printer only:
10 *FX 3, 10
is equivalent to the following direct operating system call:
10 OSBYTE=&FFF4 20 ... 1000 A%=3 :REM Select output dest 1020 X%=10 :REM Printer only 1030 Y%=0 1040 CALL OSBYTE
The assembly version is as follows:
10 OSBYTE=&FFF4 20 ... 2000 DIM P% 10 :REM allocate 10 bytes from the heap for the machine code 2010 [ 2020 LDA #3 \ Select output dest 2030 LDX #10 \ Printer only 2040 LDY #0 2050 JSR OSBYTE 2060 ] 2070 CALL P%
In the interests of saving space from avoiding unnecessary line numbers, I wanted to cram as much onto each line (without exceeding the screen width) as possible, so I used OSCLI to invoke an OS command and then put more code after it on the same line. Madness.