RTR logo

BBC BASIC for Windows

Serial and Parallel I/O



Serial input/output

You can access serial communications ports from a BBC BASIC for Windows program by treating them as files. That is, you must first open a port (using OPENUP) then read and/or write data to that port using the statements and functions provided for file input/output (BGET, BPUT, INPUT#, PRINT# etc.) and finally close the port when you have finished with it (using CLOSE). There are some differences in the way these statements and functions are used when accessing a port rather than a file, which are described below.

Most PCs have either one or two serial ports, called COM1 and (if present) COM2. However it is possible to have additional ports (COM3, COM4 etc.) if required for special purposes. BBC BASIC for Windows can access these extra ports if they have a suitable Windows™ driver.

Serial ports can only be accessed by one application at a time, so if a port is currently in use by another program, BBC BASIC will not be able to open it (the OPENUP function will return the value zero).

Opening a serial port

To open a channel to a serial port you use the OPENUP function, but instead of providing a filename you should specify a string in the following form:
port% = OPENUP("COM1: baud=9600 parity=N data=8 stop=1")
The fields within the string have the following meanings:
ParameterMeaning
baud Sets the baud rate (speed) of the port to the specified value. Permitted values are 75, 110, 150, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400 and 115200.
parity Enables or disables parity generation and checking. Permitted values are N (signifying no parity), E (signifying even parity) and O (signifying odd parity).
data Sets the number of data bits in each transmitted character. Permitted values are 7 and 8.
stop Sets the number of stop bits. Permitted values are 1 and 2.
Optionally you can include the following parameters if supported by your PC:
ParameterMeaning
xon Enables or disables XON/XOFF (software) flow-control. Permitted values are on and off.
odsr Enables or disables output flow-control using the Data Set Ready (DSR) input. Permitted values are on and off.
octs Enables or disables output flow-control using the Clear To Send (CTS) input. Permitted values are on and off.
dtr Controls the Data Terminal Ready (DTR) output. Permitted values are on, off and hs (handshake).
rts Controls the Request To Send output (RTS). Permitted values are on, off, hs (handshake) and tg (toggle).
idsr Contols the DSR sensitivity. Permitted values are on and off.
You can also use a shorthand form of the string, where the parameter values are simply separated by commas:
port% = OPENUP("COM1: 9600,N,8,1")
If the open operation succeeds, OPENUP will return a non-zero channel number. Up to four ports may be open simultaneously, with channel numbers 1, 2, 3 and 4. If the open operation fails (for example because the port is already in use) OPENUP will return zero.

Writing to a serial port

You can write data to a serial port using any of the statements provided for writing to a file. i.e. BPUT and PRINT#. These statements will not return until the data has been sent, and depending on the baud rate this can take a significant time (at 9600 baud each character takes a little over one millisecond to transmit).

Reading from a serial port

You can read data from a serial port using any of the statements and functions provided for reading from a file, i.e. BGET, INPUT# and GET$#. These will wait until the requested amount of data has been received (one byte for BGET, multiple bytes for INPUT# and GET$#) which can, of course, be an indefinite period if no data is incoming.

To avoid your program 'hanging up' while waiting for data on a serial port, you can use the EXT# function to discover how many characters (if any) are waiting to be read. If you read only that number of characters you can guarantee that your program will never be waiting a long time for data to arrive:

port% = OPENUP("COM1: baud=9600 parity=N data=8 stop=1")
IF port% = 0 PRINT "Could not open COM1" : END
REPEAT
  chars% = EXT#port%
  IF chars% <> 0 THEN
    FOR count% = 1 TO chars%
      data% = BGET#port%
      REM. Do something with the data
    NEXT
  ENDIF
  REM. Do something useful here
UNTIL FALSE

Closing a serial port

Once you have finished with a serial port it should be closed, using the standard CLOSE statement. This makes the port available to another process. As usual, executing the END statement (or an untrapped error occurring) causes all open files and ports to be closed.

The EOF# function and the PTR# pseudo-variable are not meaningful in the case of a serial port, and if used will result in the Invalid channel error.

Transferring files from a BBC Micro

If you have a working BBC Microcomputer you can transfer files (either program files or data files) from it to your PC by means of a serial link. A software utility to make this as simple as possible is supplied with BBC BASIC for Windows.

Preparation

You will need a lead to connect the BBC Micro's RS423 serial port to the COM1 serial port on your PC. The appropriate connections between the BBC Micro's 5-pin DIN connector and the standard 25 way or 9 way D-type connector used on PCs are shown below. Note that the 5-pin DIN connector is the 360° 'domino' or 'type C' variety, not the normal 'audio' type (a suitable plug can be obtained from Electron Electronics as order code 100-456). Alternatively you may be able to purchase a ready-made lead from Brockhill Enterprises.

BBC Micro PC 
DIN Plug D25 Socket  D9 Socket 
pin A<———> pin 2pin 3 Data from PC to BBC Micro
pin B<———> pin 3pin 2 Data from BBC Micro to PC
pin C<———> pin 7pin 5 Signal ground
pin D\ Connect 
pin E/ together 
 Connect /pin 4 pin 7Request to send (output from PC)
 together \pin 5 pin 8Clear to send (input to PC)
 Connect /pin 6 pin 6Data set ready (input to PC)
   |pin 8 pin 1Carrier detect (input to PC)
 together \pin 20 pin 4Data terminal ready (output from PC)

graphic

Transferring the files

To transfer files from your BBC Micro to the PC carry out the following steps:

If the transfer fails, carry out the following checks:

Converting data files

Data files transferred from a BBC Micro may need to be converted before they can be successfully read by BBC BASIC for Windows (BASIC program files should not need conversion, since BBC BASIC for Windows can read Acorn-format program files).

Data files which are read entirely using BGET# or GET$# will not need conversion. However, files which are read using INPUT# or READ# must be converted using the FCONVERT utility supplied (it can be found in the EXAMPLES\TOOLS directory).

Data files read with a mixture of BGET# (or GET$#) and INPUT# (or READ#) are a nuisance. It may be possible to convert them, but you will get a number of 'Bad data' errors reported and you may confuse the FCONVERT utility. If this happens, you will need to write your own data conversion program and in order to do this you will need to know the structure of the data file and the way data is stored by the Acorn version of BBC BASIC.

Parallel input/output

In a similar way to the serial ports, you can open a channel to a parallel (printer) port as if it was a file. You might want to do that in order, for example, to control an unusual printer which has no Windows™ driver or if a device other than a printer is connected to the port. Note that a suitable device implementing the 'Centronics' interface protocol must be connected; you cannot use this method to output 'raw' data to the parallel port.
port% = OPENUP("LPT1:")
Unlike the serial ports, no parameters need to be specified. Normally you can only write to a parallel port, although you may be able to read from a bi-directional port in some circumstances.

Most PCs have just one parallel port, called LPT1. Parallel ports can only be accessed by one application at a time, so if a port is currently in use by another program, BBC BASIC will not be able to open it (the OPENUP function will return the value zero).

If a printer is already installed on the specified port, attempting to open the port may fail (depending on the operating system version and printer driver in use). In that case you should write to the printer using the normal methods, i.e. using VDU 2 etc.

Direct port input/output

In special circumstances you may wish to access input/output ports directly, for example to interface with and/or control external devices. Typically such devices will not have Windows™ drivers nor be supported by any operating system calls.

Input/output using InpOut32

Windows™ NT (including Windows 2000, XP, Vista, Windows 7, 8/8.1 and 10) prohibits direct low-level access to input/output ports from user programs; in so doing it provides better protection against applications interfering with each other or crashing the computer. For this reason you must use a special device driver to achieve such access; a suitable driver of this kind is InpOut32 which can be downloaded from here.

You should copy the file inpout32.dll from the downloaded ZIP file (probably in the Win32 subdirectory) to your BBC BASIC for Windows library folder (usually C:\Program Files\BBC BASIC for Windows\LIB\). Under Windows Vista™, Windows 7™, Windows 8/8.1™ or Windows 10/11™ you will need administrator privileges to do that.

To use InpOut32 incorporate the following code in your BASIC program:

SYS "LoadLibrary", @lib$+"inpout32.dll" TO inpout32%
IF inpout32% = 0 ERROR 100, "Cannot load inpout32.dll"
SYS "GetProcAddress", inpout32%, "Inp32" TO `Inp32`
SYS "GetProcAddress", inpout32%, "Out32" TO `Out32`
Once this code has been executed, you can read from an input port using the following statement:
SYS `Inp32`, portaddress% TO portdata%
Similarly, you can write to an output port using the following statement:
SYS `Out32`, portaddress%, portdata%

If using InpOut32 with a 'compiled' BASIC program you must ensure that inpout32.dll is available; this can conveniently be achieved using the following Compiler Directive:

REM!Embed @lib$+"inpout32.dll"
When InpOut32 is used on Windows Vista™, Windows 7™, Windows 8/8.1™ or Windows 10/11™ BBC BASIC for Windows (or your compiled program) must be run in administrator mode. One way of doing that is to right-click on the desktop icon and select 'Run as administrator'. If you want to avoid the inconvenience of doing that, the InpOut32 ZIP file contains the utility InstallDriver.exe; instructions for using it are in the file ReadMe.txt.

Assembly language I/O

Windows™ 95, 98 and Me permit direct access to the hardware ports using the processor's in and out instructions. Although BBC BASIC for Windows has no keywords to perform such access, you can easily achieve it by means of assembly language code. The simplest code to achieve this is as follows:
DIM P% 6
[OPT 0
.inport in al,dx : movzx eax,al : ret
.outport out dx,al : ret : ]
Once this code has been executed, you can read from a port using the following program segment:
D% = address%
data% = USR(inport)
The static variable D% is first loaded with the port address (this gets copied into the processor's edx register), then the data is read from the port using the USR function.

Similarly, you can write to a port using the following program segment:

D% = address%
A% = data%
CALL outport
Here D% is loaded with the port address and A% is loaded with the data value (they get copied into the processor's edx and eax registers respectively) and the actual port write is performed using the CALL statement.

Note that, as stated previously, this method will only work with Windows™ 95, 98 and Me.

Modem control input/output

An alternative form of parallel input/output, and one which will work with all versions of Windows™ without the complication of a special driver, is the use of the modem control lines on a serial port. Each serial port (COM1, COM2 etc.) has a number of input/output signals in addition to the serial data lines; traditionally these are used to control, and receive status information from, a modem connected to the port. They may also be used for handshaking between two serial ports (for example, a receiving device might use one of these lines to cause the sending device to pause transmission).

When not used for these purposes, the modem control and status signals are available for user I/O. The only special feature to note is that the voltage levels on these lines (generally) correspond to the RS232 specification, that is they swing from a negative voltage (in the range −5 Volts to −12 Volts) to a positive voltage (+5 Volts to +12 Volts).

The signals available for this use, and the corresponding pins on the serial port connectors, are as follows:

Name Direction D25 socket D9 socket
RTSoutputpin 4 pin 7
CTSinputpin 5 pin 8
DSRinputpin 6 pin 6
CDinputpin 8 pin 1
DTRoutputpin 20 pin 4
RIinputpin 22 pin 9
GNDgroundpin 7 pin 5

Modem control output

The RTS and DTR output signals may be controlled as follows:
com% = OPENUP("COM1:9600,N,8,1")
IF com% = 0 ERROR 0,"Could not open serial port"
REM. Set RTS:
SYS "EscapeCommFunction", @hfile%(com%), 3
REM. Clear RTS:
SYS "EscapeCommFunction", @hfile%(com%), 4
REM. Set DTR:
SYS "EscapeCommFunction", @hfile%(com%), 5
REM. Clear DTR:
SYS "EscapeCommFunction", @hfile%(com%), 6
CLOSE #com%

Modem status input

The CTS, DSR, CD and RI input signals may be tested as follows:
com% = OPENUP("COM1:9600,N,8,1")
IF com% = 0 ERROR 0,"Could not open serial port"
SYS "GetCommModemStatus", @hfile%(com%), ^modemstatus%
CLOSE #com%
The variable modemstatus% will contain a value corresponding to the states of the inputs as follows (the values may be combined):
CTS  16
DSR32
RI64
CD128

Left CONTENTS

CONTINUE Right


Best viewed with Any Browser Valid HTML 3.2!
© Richard Russell 2021