Control ROM Front Page

Control ROM Documentation

Contents

Introduction
Turtle Graphics and Commands
Use of BASIC's Resident Integer Variables
    *Result Page <n>
*Sin and *Cos
I/O Commands
    Other Commands
Error Messages
Appendix – Some Technical Details
    Graphics File Format
    Private Page Use
    Use of Page Zero
    Use of Page One
    OSGBPB (&FFD1) Control Block
    To Do - Potential Improvements For a New Version


#Introduction

The Economatics Control ROM was written to control models built with the fischertechnik Computing Experimental kit on BBC computers (B, B+, and Master versions, but not the Master Compact). The physical control interface was the Economatics Interface, which is probably completely unobtainable now. It was not intended for people to write their own programs although they are perfectly at liberty to do so The ROM was necessary to support software originally written for the IBM PC and then ported to the BBC Micro. There was not enough space in the 32k of a BBC Computer, so the decision was taken to put as much as possible in a ROM. In practice this meant all the I/O commands and turtle graphics, and the specialist commands to run a model buggy that was one of the projects to build with the fischertechnik kit. After a year or two, fischertechnik produced a version of their interface for Acorn computers to ship with the Computing Experimental kit, and so the Economatics interface was redundant, and the Control ROM was not updated.

The Control ROM was required to be fitted to a BBC Micro (or Master) so that the various pieces of software could be run, to control the various models buildable with the Computing Experimental kit. In practice, I suspect that the only realistic user of the ROM was me, in writing the software for each model, I never heard of anyone playing with the ROM or writing their own routines.

In the ROM, extensive use is made of the internal "%" integer variables in BASIC, (A%, B%, and so on) both for input and output into the ROM routines. Again, it was never intended for the ROM to be used for users' own programs even though the facility was there should anyone want it. For that reason the command "*Result Page should not be used without knowledge of how to use it and what effect it might have.

With the unavailability of interfacing hardware, the main use of the ROM nowadays will be for the turtle graphics package that it contains, which is fast and accurate. The other use, which may be of interest to some are the fast integer trigonometry routines *Sin and *Cos.

Commands to the Economatics Control ROM are given in “Star command” format, ie, a line of text preceded by a star. This can be done from many different languages, including BASIC, or using the BBC Micro’s OSCLI command line interface capability from, say, a machine code program.

It should be remembered that I was severely restricted in what the ROM had to contain, it was designed to support software written for specific models in the fischertechnik Computing Experimental kit, which I translated from a version of BASIC on the IBM PC, and to support that I translated the 50,000 word handbook from German and wrote the ROM.

Ben Newsam, 2024


#Turtle Graphics and Commands

Turtle graphics use an imaginary robot called a “turtle” to draw lines. The turtle has a location, a heading, and a “pen” with which it can draw. All turtle movements or changes in heading are based on its previous position. Thus, giving the turtle two commands to move “Forward 100” would result in the turtle travelling a total of 200 units along its current heading. In the Control ROM, the turtle graphics environment is started in a graphics MODE (0,1,2,4, or 5). The chosen MODE should be entered and the command “*Graphics On” given. If the computer is in a text-only MODE, an error message appears.

Example:

MODE 1
*Graphics On

Commands available to control the turtle graphics are:

*Graphics On

The bottom six lines of the screen are reserved for text, and the rest of the screen becomes a graphics window with a triangle representing the “turtle” in the centre of the screen, pointing upwards. The turtle size, “slant” and heading are all reset to their default values.

*Graphics Off

The screen returns to the chosen MODE with a text cursor at the top of a blank screen.

*Forward <n>

The turtle moves forward the chosen number of virtual screen units.

*Back <n>

The turtle moves back the chosen number of units.

*Left <a>

The turtle turns to the left through the chosen number of degrees.

*Right <a>

The turtle turns to the right through the chosen number of degrees.

*Read X

Returns the turtle’s X coordinate in the X% variable.

*Read Y

Returns the turtle’s Y coordinate in the Y% variable.

*Read Angle

Returns the turtle’s current heading in the A% variable.

*Read Colour

Returns the screen colour at the turtle’s current X & Y coordinates in the C% variable.

*Pen Up

Lifts the “pen” so that the turtle leaves no trace as it moves.

*Pen Down

Drops the “pen” so that a line is drawn as the turtle moves. The default pen position after “*Graphics On” is “Down”.

*Pen Colour <c>

Changes the colour of the line drawn by the turtle.

*Turtle On

Makes the triangular turtle visible.

*Turtle Off

Hides the turtle from view. A “*Turtle Off” command speeds up drawing considerably.

*Turtle Colour <c>

Changes the colour of the triangular “turtle”.

*Turtle Size <n>

Changes the size of the turtle from its point to its back. Sensible sizes are from about 20 to 100

*Turtle Slant <a>

Changes the angle of the sides of the turtle. Useful numbers are from about 120 to 170

*Graphic Load <filename>

Loads a graphics file in a particular format to be used as a background for turtle movements in certain of the kit’s software.

*Graphic Save <filename>

Saves the current screen in a special format peculiar to the Control ROM. This was used to produce the backgrounds required by the kit’s software.

*Graphic Newscreen

If a “*Graphic Save <f>” or “*Graphic Load <f>” has been done since the last “*Graphics On” command, it reload sthe previous graphics file, otherwise the screen is cleared and the turtle returns to the centre, turtle size not being altered.

where:

<a> is an angle in degrees
<c> is a valid colour in the current screen MODE
<n> is an integer number, or one of BASIC’s resident “%” variables (for example “*Forward N%”)

Notes:

“*Graphic” is synonymous with “*Graphics”
“*Graphics Enable” is the same as “*Graphics On”, but “*Turtle Enable” will cause an error.
All commands may be in upper or lower case. The convention here is to capitalise all command words.


#Use of BASIC's Resident Integer Variables

Where a number is expected on the command line, one of BASIC’s resident integer variables may be used instead. For instance "*Forward D%" or "*Right N%".

After certain commands, the contents of some of the resident integer variables will be changed. It is important to be aware of this fact when writing programs in BASIC.

A%

After every buggy or turtle movement, the turtle or buggy's heading is in A%.

A%..D%

A% and B% are inputs to "*Sin" and "*Cos", C% and D% are the results.

A%..H%

Contain the state of switches 0..7 after "*Read Switches"

C%

Holds the result of "*Read Colour"

E%

Starts with a value of 162 after *Graphics On or *Graphics Newscreen. I think this is because the default "turtle slant" is 162 degrees. After that it keeps track of turtle turns by adding angles to the right and subtracting to the left. Ideally, E% should have been set to zero at *Graphics On or *Graphics Newscreen, but what is done is done, it's a bug. Anyway, it offers a potential means of keeping track of a "Total Turtle Trip" [q.v.], you just have to remember to deal with the 162.

L%

Holds the results of "*Read Analogue L".

S%

Contents of &0124 after buggy movements. I don't know why, it was probably for debugging purposes and got forgotten about.

T%

Holds the results of "*Read Analogue T"

X%

After every turtle or buggy movement, the latest X position is in X%.

Y%

After every turtle or buggy movement, the latest Y position is in Y%.

#*Result Page <n>

BBC BASIC has 27 internal integer variables, A% to Z% and also the system variable used for formatting @%. These are stored in the computer's memory in Page 4, i.e. locations &0400 to &0468. Each variable takes 4 bytes (32 bits), so @% is at &0400, A% at &0404, B% at &0408, C% at &040C and so on. The Control ROM makes extensive use of these "percent variables" for output (for example, the heading and position of the screen turtle is returned in A%, X%, and Y%). Since the Control ROM could conceivably be used from languages other than BASIC and Page 4 might not be available, it is possible to specify a different location by using "*Result Page" followed by the page number to be used. This should only ever be used to point to a safe page of memory that is not used for any other purpose. In practice, it is unlikely that this will ever be needed.


#*Sin and *Cos

SIN and COS functions are needed in the Control ROM to determine new positions for the turtle in the turtle graphics routines. Because the SIN and COS routines in BASIC may not be available (a different language might be used instead), the Control ROM uses much faster integer-only routines that use a 91-value 8-bit lookup table. This low level of precision is all that is needed to fix the position of any pixel on the screen relative to any other. The *Sin and *Cos commands are provided to allow users access to to the ROM's fast internal trigonometry routines.

Input to the routines is a heading in degrees in A% and a multiplier in B% that is usually a distance in logical co-ordinates. Note that the convention used in the ROM for angles is degrees clockwise from "North", like a compass. This differs from the strict mathematical approach (zero degrees points to the left in the X direction), but makes more sense from a human perspective (for navigation with a map, say), and is also compatible with other software using turtle graphics such as LOGO.

The basic result is returned in C%. If B% is a distance, C% will give the new X coordinate after *Sin, or the new Y coordinate after *Cos. Dividing the result in C% by the multiplier in B% will give a result that might usually be expected from BASIC’s SIN or COS routines. So for instance after A%=45 and B%=1000, "*Sin" returns C% with 708. C% divided by B% gives 0.708, compared to the more usual 0.7071 when SIN RAD 45 is used from BASIC. That's close enough FOR BBC Micro graphics. There is no need to actually do the division if B% is the wished-for distance. After *Sin, C% will already be the relative distance to travel in the X direction. *Cos will do the same for the Y direction.

A worked example: if the turtle is at position 100,100 and has a heading of 70 degrees, a *Forward 100 command would take it to position 194,134. This can be obtained using *Sin and *Cos thus:

A% = 70:REM Turtle heading in degrees
B% = 100:REM Distance to travel
*Sin

C% now holds 94, AND D% is 62

Then after *Cos, C% is 33 and D% is 109. PLOT 1,94,33 will draw a line to the new point. Only one screen unit out, so not too bad, and the new point will almost certainly be the correct actual pixel in any given MODE.

The contents of D% can be used for adjustment. The value in D% is an 8-bit signed integer, which means that it can hold a number between -128 and 127. If it is less than -64 or greater than 63, then the distance in that direction may be adjusted by one. In the *Cos example above, D% is 109, and so, being more than 64, the distance can be corrected so the move then becomes PLOT 1,94,34 which is what we would expect. Anything left over could possibly be stored and merged into the next turtle movement.

To see the actual contents of the lookup table, the following will provide it:

B% = 127
FOR A%=0 TO 90
  *Cos
  PRINT C%;
NEXT

For comparison, in Logotron LOGO with the turtle at position 0,0

RT 70 FD 100 PRINT XCOR PRINT YCOR

results in

93.969 34.202

From this it can be seen that LOGO keeps track of fractions of logical units even though in the default MODE 4 a single physical pixel covers 4 logical units in each direction, a total of 16 logical positions. This use of fractional logical units makes for greater accuracy. The Economatics Control ROM does the same, but in a different way, using integers. The turtle’s position is reported in whole numbers of logical units in the X% and Y% variables, and the fractions of units are stored away internally ready for the next move. The fractional part of each calculation can be obtained after *Sin or *Cos in D%, but is unlikely to be of much use in practice.


#I/O Commands

Here are all the commands concerned with I/O, that are of no use at all without the relevant hardware interface. The interface had 8 single bit inputs (“Switches”), 8 output lines arranged in pairs for the control of motors, and 2 analogue inputs, designated as “L” and “T” for some obscure and forgotten reason:

*Output <o> Off
*Output <o> Left
*Output <o> Right
*Output <o> Both
*Output <o> Forward
*Output <o> Back

Outputs were arranged in pairs for motor control. Individual outputs could be turned on or off by judicious use of “Left”, “Right”, “Off” and “Both”, but I cannot remember exactly what combination of outputs were set by “Forward” and “Back”.

*Output Brake <b>

When motors were turned off, they were given a brief pulse in the opposite direction to prevent overrun, which was especially important for a mobile buggy. <b> was an unsigned 8-bit value specifying arbitrary units of time for the braking pulse. Higher numbers gave a longer pulse. The default was 6.

*Read Analogue L
*Read Analogue T

Results were read into L% and T% respectively.

*Read Buggy X
*Read Buggy Y
*Read Buggy Angle

Results were read into X%, Y% or A% respectively.

*Read Switches

Results were read into variables A% to H%

*Buggy Initialise

Required command before issuing commands to the buggy.

*Buggy Left <a>
*Buggy Right <a>
*Buggy Forward <n>
*Buggy Back <n>

Buggy movements were controlled by starting the two drive motors in the relevant direction, and then counting pulses from a switch that was pressed by a rotating cam. At the end of each movement, a braking pulse was applied in the opposite direction to prevent overruns. Forward and Back pulses were an arbitrary but short distance, and for turns, each pulse represented a turn of 5 degrees. After a movement, the buggy’s position and heading were returned in X%, Y%, and A%.

*Initialise

Initialised the hardware interface. Many I/O commands generate an error until this command has been given.

In the above:

<a> is an angle in degrees
<b> is a byte value 0..255
<n> is an integer
<o> is a number from 1 to 4, being an output pair to control a motor. Outputs could be controlled individually to switch, for instance, lights on or off by using “*Output <o> Left” or “Right”.

Any of the above could be replaced by a BASIC resident integer variable (A%..Z%) containing a value in the expected range

#Other Commands

A few more commands not concerned with I/O:

*Help Hardware

Displays the former address of Economatics Education Limited, the company from whom interfaces could be obtained.

*Author

My street address and phone number when I wrote the ROM! Not many people knew about this command, and in fact I moved it from "*Help Autor" at the last minute in order to hide it a little bit! The ROM contains my personal copyright notice, which can be seen using, say, the Hackers ROM.

*Graphic Dump

This does nothing. It just displays “Routine not written yet” on the screen, even though is not strictly an error message and has no error number.


#Error Messages

Here are all the error messages likely to be displayed by the Economatics Control ROM In general, they are not all that helpful to users writing their own software, they were really meant only for me while developing the Computing Kit programs.

&64 100 "Economatics ROM syntax error"

This error occurs when unexpected text appears in a Control ROM command line, such as using “*Output On” instead of “*Output 1 On”.

&64 100 "Economatics ROM syntax error"
&65 101 "Word missing from line”

Self-explanatory. For instance “*Output” or “*Graphics” with nothing to follow.

&66 102 "No such colour"

This occurs when a colour is specified outside the range of colours for the current MODE.

&67 103 "Not in graphics MODE"

This occurs if “*Graphic On” is issued when in MODE 3, 6, or 7.

&68 104 "Greater than 255"

This happens if a value greater than 255 is given in an “*Output Brake <b>” command.

&69 105 "Buggy not initialised"

The buggy must be initialised before it can be controlled.

&6A 106 "Not a multiple of 5"

The buggy can only turn 5 degrees at a time.

&6B 107 "Number missing"

Some commands need a number (or integer variable name) to be valid.

&6C 108 "Bad variable name"

This will happen if, for instance, “*Forward s%” is issued (The “s” is lower case, and the command only accepts the internal upper case “%” variables).

&6D 109 "Arithmetic overflow"

I think that this error message can never happen!

&6E 110 "Interface not initialised"

An attempt has been made to issue an I/O command without “*Initialise” first.

The following are all used in connection with “*Graphic Load” and “*Graphic Save”. And are mostly self-explanatory.

&6F 111 "Filename too long"
&70 112 "Graphic file not found"
&71 113 "Not a graphics file"

Files loaded with “*Graphic Load” must be in the specific format as saved with “*Graphic Save”.

&72 114 "Wrong graphics MODE"

I am not sure exactly what causes this error.

&73 115 "Can't open file"

Self-explanatory. Can't open the specified file (after *Graphics Load or possibly *Graphics Save)

&74 116 "Graphics not enabled"

Turtle graphics commands can only be given when turtle graphics have been enabled with “*Graphics On”.

"Error" message with no number, in response to *Graphic Dump:

      "Routine not written yet"


#Appendix – Some Technical Details

#Graphics File Format

Graphics File Format for “*Graphics Load <f>” and “*Graphics Save <f>” commands

Byte - 99 - Identifier, must be present
Byte - Screen MODE
Byte - Screen memory map type 0..4, mapping to 20k,16k,10k,8k,1k
Byte - Number of logical colours -1
Bytes - <n> - Defined colour for each logical colour
Bytes - <s> - Screen dump

where:
<f> is a valid filename,
<n> is the number of colours in the specified screen MODE,
<s> is the number of bytes of screen memory used for the specified MODE.

#Private Page Use

The Control ROM reserves one page for its own private use. This means that when the ROM is in the computer, PAGE in BASIC is raised by one page of memory. Thus, if without the ROM, PAGE is &1900, with the Control ROM installed it will be &1A00. The exact location of the private page depends on the memory claimed by other ROMs, and in which socket the ROM is installed. In BASIC it is possible to find out which page has been claimed with:

S% = <socket number of ROM>
PRINT ~?(&DF0+S%)*&100

Table of private page use and default values:

Offset Description On Break After *Initialise After *Graphics On
&00Contents of &88[1]0
&01Flag for "Interface enabled"01
&02Flag for "Graphics enabled"001
&03Flag for "Buggy Initialised"00
&04Flag for "Turtle on"011
&05Flag used for the turtle[2]001
&06Turtle colour1
&07Turtle size[3]&28&34
&08Turtle "slant"[3]&A0&A2
&09Pen colour7
&0APen state flag (1=down, 0=up)11
&0BContents of &89[1]0
&0CCurrent screen MODEn
&0D..&1AControl block for OSGBPB
&1B..&1DUnused
&1E..&31Filenames for Graphics&0D&0D
&32Output mask byte for motors0
&33Value for "*Output Brake"6
&34Not used0
&35Result page[4]4
&36..&55Temporary copy of Page 0 from &70..&8F
&56..&D5Temporary copy of Page 1 from &100..&175[5]
&D6..&FFUnused

Notes:

[1] These are mask bytes used in I/O routines.
[2] Seems to be toggled when the turtle is drawn.
[3] The default values on Break are redundant, as they will always be set to other values after “*Graphics On”.
[4] The default of 4 (ie, page 4 of memory, or &0400) is where BASIC keeps its resident integer variables (A%..Z%). Another page could theoretically be used (using “*Result Page <n>”, provided that it is safe from being overwritten.
[5] At certain moments, page zero locations &70..&8F are copied into the private page, to be restored later, and locations &100..&17F are filled with data from the private page, and returned later. The two operations should not be confused.

#Use of Page Zero

32 bytes from &70 to &8F are copied into the private page at the start of Control ROM routines that use Page Zero, and restored again afterwards. This area of memory is available for the Control ROM to use at will during any one routine, and thus should not affect other ROMs using this space.

&70, &71 - Used as address for textOut, storeInPrivatePage, readFromPrivatePage, executeBRK
&72, &73 - Used by readSwitches for pointer into result integer variables
&74, &75, &76 - Used by Buggy routines
&77, &78 – Not used
&79, &7A, &7B - used as temporary stores by div, graphics Load and Save routines
&7B, &7C - used in getArgument
&7C, &7D, &7E, &7F - used for addresses in getArgument
&80 - used in getArgument
&81 - used in inputCommand
&82 - used in textOut, getArgument
&83 - used in getArgument
&84 – Not used
&85 - used in readSwitches, brakeMotors, outputNumber
&85, &86, &87 - used in loadRegisters and saveRegisters, and thus in getAnalogue and readSwitches, also initialiseInterface
&88, &89 - used in initialiseInterface
&8A, &8B - used by Buggy routines
&8C, &8D - Used as the address of source in copyMemory
&8E, &8F - Used as the address of destination in copyMemory and zeroMemory

Other use of page zero:

&F2, &F3 - Holds the address of the command line &F4 - ROM number - this is read from but obviously never written to

The following are safe to use with BASIC, but possibly not with other languages. The main memory-copying routine used in the Control ROM is copyMemory. An additional memory-copying routine "copyMemA" was written hurriedly so that it could move areas of Page Zero about, including &8C to &8F, both of which are used by copyMemory. copyMemA could be used as the only memory copy routine, but it would be a huge job to change everything, so I didn't bother. One for the future.

&&F6, &F7 - Used as the address of source in copyMemA
&F8, &F9 - Used as the address of destination in copyMemA

&FF - used to test for a press of Escape in bit 7

#Use of Page One

Page 1 locations are divided into 4-byte "registers", meaning that all calculations in the Economatics Control ROM are done with 32-bit integers. Each "register" is usually referenced by its starting byte.

Although other ROMs use this area of memory, Control ROM use can persist from one call to another because the first 128 bytes are copied from the Private Page into page 1 at the start of an operation and stored away again at the end.

&0100 - The "accumulator". All mathematical operations leave their result in here. Many other routines also return a result in the accumulator, for instance getColour and readNumberOrVariable
&0104 - The "subtractor". This register may be used for various purposes, but the subtract routine always subtracts this register from the accumulator and returns the result to the accumulator.
&0108 - Multiplicand register, also remainder from division and a temporary store for turtle "slant"
&010C - Various, including dividend and quotient for division
&0110 - Working register, used extensively in Buggy routines
&0114 - Used in Buggy and turtle routines
&0118 - Various, including divisor
&011C - Screen turtle heading (X & Y are read directly from the OS)
&0120 - Used in Buggy and turtle routines
&0124 - Mainly used for distances for trig routines (Buggy and turtle forward or back)

&0134 - Buggy heading
&0138 - buggyX
&013C - buggyY
&0140 - buggyErrorX
&0144 - buggyErrorY
&0148 - errorX
&014C - errorY

&0150 onwards - Error messages for BRK processing, also used for parameters to PLOT routines.

&0180 (one byte only, not a 4-byte “register”) - Used to store contents of A ready to pass to the next ROM, or set to zero to cancel that.

#OSGBPB (&FFD1) Control Block

OSGBPB (&FFD1) is called with the address of a 13-byte control block in X & Y, and the reason code for the call in A

In the Control ROM, the control block used for OSGBPB is located at &pp1E, where "pp" is the ROM's private page, and should be set up as follows:

Control block
-------------
00 - File handle
01..04 Pointer to data location, low byte first.
05..08 Number of bytes to transfer, low byte first.

Contents of A
-------------
2 – Save bytes
4 – Load bytes

#To Do - Potential Improvements For a New Version

Where routines such as compare, copyMemory, zeroMemory etc always work on 4 bytes, move the ldx #&04 to inside the routine rather than have it as a parameter. This will save a lot of bytes especially where routines are called a lot, copyMemory in particular. If a different number is used, in particular for zeroMemory, jsr a different address.

At a later date, organise all the I/O routines into one place, and vector them out so they can be replaced. It would also be good if the ROM is making no assumptions about motors or switches, although this might not be feasible.

Document how the 4 byte "registers" are used, if it actually makes sense. For instance, &0100 is the accumulator, etc.. As an example, the add routine always adds into the accumulator from a register specified in X & Y.

The routine at 98D8 (don't know what it is called) can be moved to the only place from which it is called.

Get rid of the callDoGraphicsOn routine. All it does is call doGraphicsOn and returns. Call doGraphicsOn directly.

Prevent "*Buggy Initialise" from locking up when no buggy or interface is connected.

Investigate whether to merge copyMemory and copyMemA. CopyMemA uses different Page 0 locations, so I need to be sure that it is safe to change this.

Improve checking for valid MODEs in "*Graphic Load". At the moment, higher numbers of MODE cause problems on the BBC Master. Just a thought: if a file is saved on a BBC Master in a higher numbered MODE using “@Graphics Save <f>”, what will happen if the file is reloaded on a Model B? It might be possible to fix this. Possibly a good way to achieve this is to save the size of file rather than the actual MODE. Don’t know.

In "*Output Brake", check all upper bytes of the "accumulator" &0100 to cause "Greater than 255" error, otherwise "*Output Brake 65536" would be accepted as input. At the moment, only &0101 is checked for being non-zero, which works in most cases but is somewhat lazy. Anything negative or over 255 should be rejected, but in fact at the moment silly things like "*Output Brake 2147418367" are accepted (&7FFF00FF). Best way is to add "ora &0102:ora &0103" etc., before testing.

Change the default private page values for locations &07 and &08 to &34 and &A2 (turtle size and turtle slant). This will make no difference to actual operation, because "*Graphics On" has its own default values (&34 and &A2). In fact, any defaults for the turtle do not need to be set up here at all, as they will always be overwritten by "*Graphics On", so they might as well be removed.

Possibly remove the *Turtle Slant command altogether. Keep *Turtle Size

Add an option to have a number as input to the *Pen command, to be saved in the same place as the "Pen Down" flag, so that different PLOT types can be used.

Remove redundant lines from doResultPage. &pp34 is never used.

Remove redundant "stx &8E:sty &8F" from calls to twosComplement

Move "stx &8E:sty &8F:lad #&04" into .compare

"*Graphic Dump" is not used, so it can be removed, along with its error routine and message.

Because of the unavailability of the Economatics Interface, if I were to recompile the ROM, I would provide vectors so that people could write their own I/O routines.

Replace the calls to OSGBPB by writing faster routines for *Graphic Load and *Graphic Save, if that is possible. Investigate.