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 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.
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 via any operating system calls.

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. Windows™ NT4, 2000 and XP, however, prohibit direct access to the ports by this means (in so doing they provide better protection against applications crashing the computer) and you must use a special device driver to achieve it. A suitable driver of this kind is supplied with BBC BASIC for Windows (see below).

Assembly language I/O

To make use of the processor's in and out instructions you must incorporate a small amount of assembly language code in your BASIC program. 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. It will not work with Windows™ NT4, 2000 or XP. For those operating systems the method described below (or an equivalent) must be used.

Input/output using WINIO

WINIO is a special device driver which can be used to access input/output ports from BBC BASIC for Windows. WINIO is a third-party product (see http://www.internals.com) and is supplied with the permission of the author Yariv Kaplan. The file WINIO.CHM, which can be found in the BBC BASIC for Windows folder, contains details of WINIO and its conditions of use.

WINIO can be used with all versions of Windows but is of particular value with Windows™ NT4, 2000 and XP because direct hardware port access is prohibited by those versions. Note that you must have administrative privileges to install WINIO on those systems.

BBC BASIC for Windows versions 4.00a and later are supplied with version 2 of WINIO, which is compatible with Windows™ XP. However it seems to be incompatible with Windows™ 95, 98 and Me so the earlier version of WINIO can be found in the BBC BASIC for Windows folder as WINIOV1.DLL and WINIOV1.SYS.

To use WINIO you must incorporate the following code in your BASIC program:

SYS "LoadLibrary", "WINIO.DLL" TO winio%
IF winio% = 0 ERROR 0, "Could not load WINIO"
SYS "GetProcAddress", winio%, "InitializeWinIo" TO InitializeWinIo%
SYS "GetProcAddress", winio%, "ShutdownWinIo" TO ShutdownWinIo%
SYS "GetProcAddress", winio%, "GetPortVal" TO GetPortVal%
SYS "GetProcAddress", winio%, "SetPortVal" TO SetPortVal%
SYS InitializeWinIo% TO ok%
IF (ok% AND 1) = 0 ERROR 0, "Could not initialise WINIO"
Once this code has been executed, you can read from a port using the following program segment:
SYS GetPortVal%, address%, ^portdata%, 1
The GetPortVal function is passed the port address, a memory location in which to return the data, and the data width of the port in bytes (usually 1).

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

SYS SetPortVal%, address%, portdata%, 1
The SetPortVal function is passed the port address, the data value to be written and the data width of the port in bytes (usually 1).

Once you have finished with WINIO, you should close it down by calling the ShutdownWinIo function:

SYS ShutdownWinIo%
WINIO.DLL, WINIO.SYS and WINIO.VXD must be in the same directory (folder) as the executable program using them. So when running a BASIC program from the interactive environment they must be in the same directory as BBCWIN.EXE (or BBCWDEM.EXE); this is the normal situation following installation. If using WINIO with a 'compiled' program you must ensure that its files are in the same directory as your executable; this can conveniently be achieved using the embedded files feature of the Compile utility.

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 2007