
                      ***************************
                      HeliOS ADDER motor routines
                      ***************************

************
Introduction
************

The HeliOS ADDER routines are part of the interrupt-driven game operating
system and function as one of the HeliOS "motor" routines.

These are fast optimised machine coded routines which can be controlled
entirely by pre-defined data structures.

These functions only work in HeliOS mode.

HeliOS ADDER functions allow fast and efficient performance of simple
calculations synchronously with other functions performed by the interrupt
driven HeliOS system.

ADDERs are designed to allow multiple addition and/or subtraction of numbers
specified by pointers and/or fixed values.  Complex series of additions and
subtractions can be set up, with inter-reference between calculation stages.

The results of ADDER functions can be stored into any number of external
locations, and this ability makes ADDERS useful for distributing values into
a multiplicity of target pointers.

Take care to study the "Adder_Flags" field of the control data structure
which controls several different modes of ADDER operation.  The most useful
function is to control whether the ADDER works on a null value each time or
whether it works accumulatively by saving and adding in the results of all
previous operations.

ADDERs are often used for coordinate calculations and perform simultaneaous
processing on X and Y coordinate values: if you are using the ADDER for
other purposes you are, of course, free to use each of the X and Y stages
in any way appropriate to the task your code is performing.

These ADDER functions allow interactions between data structures to be set
up which will run fully automatically in the background.

Using pre-defined control data structures, along with direct programmability
if required, you can generate a number of different control functions.

These routines have many applications, in particular they allow linkage
between events occurring in different sub-systems.

It is impossible to list all the possible ways of using these highly
flexible routines, and it will be easier to see the potential of this
system after examining how it works.

It is worth pointing out that all HeliOS motor functions are not only
pre-programmable, but they operate in a mutually self-programming way by
allowing "modifiers" and "results" to operate on other motors.  In other
words input and output from motor programs do not only work with parameters 
stored in their own "private" data structures: motors can also read inputs
and distribute results by interacting with control data structure fields
of other motors or any other computed objects.

This INDIRECTION of input and output, a feature common to ALL HeliOS
data objects, allows complex interlinking and self-programmability.

The mutual self-programmability of HeliOS objects means that the results
of one operation can be used to automatically program another, which in
turn can (re)act on the first....and so on.

All this can be set up to work automatically without you having to do any
intermediate programming to manage all the interactions.

This means, in other words, that all HeliOS motors can PROGRAM EACH OTHER,
so input or output data can be modified by other motor functions and can
in turn program other motors.

This mutual programmability combined with the BEFORE and AFTER functions
give the HeliOS motor functions considerable power from ultra fast and very
simple routines.

******
Timing
******

It is an important consideration that all motor functions are fully
synchronised with all other HeliOS internally automated functions and
with the display frame rate.

Motors are run in the order in which they are installed: you must remember
this if you are using one motor function to modify another.

******************
Control structures
******************

The main ADDER control structure is as follows:

-----------------------
ADDER control structure
-----------------------

Adder_BeforeForth(w) = HeliOS CFA to run BEFORE each ADDER calculation
Adder_BeforeCode(l)  = Machine code to run BEFORE each ADDER calculation
Adder_AfterForth(w)  = HeliOS CFA to run AFTER each ADDER calculation
Adder_AfterCode(l)   = Machine code to run AFTER each ADDER calculation
Adder_Flags(w)       = Control flags word ( See below)
Adder_CountDown(w)   = Countdown time (If non-zero sets countdown)
Adder_CDFlags(w)     = Countdown flags word (-> "Flags" at CountDown time)
Adder_CDForth(w)     = Countdown HeliOS function CFA (optional)
Adder_CDCode(l)      = Countdown machine code function pointer (optional)
Adder_SkipTimer(w)   = ADDER skip internal timer register
Adder_SkipCount(w)   = ADDER skip count = How many "ticks" to skip (0=Do all)
Adder_ID(w)          = Motor handler ID = 0 for ADDER
Adder_XResult(w)     = X-Calculation final result store
Adder_YResult(w)     = Y-Calculation final result store
Adder_AddCount(w)    = Number of ADDER calculation data blocks
Adder_AddData(l)     = ADDER calculation data list pointer
Adder_StoreCount(w)  = Number of ADDER data storage blocks
Adder_StoreData(l)   = ADDER data storage list pointer
Adder_UserDataPtr(l) = Free user data pointer
Adder_UserData1(w)   = Free user data1
Adder_UserData2(w)   = Free user data2
Adder_UserData3(w)   = Free user data3
Adder_UserData4(w)   = Free user data4
Adder_UserData5(w)   = Free user data5
Adder_UserData6(w)   = Free user data6
Adder_UserStatus(w)  = Free user status

Here is an amplified description of each field:

Adder_BeforeForth   This field, if non-null, contains the CFA af a HeliOS
                    command which will be run BEFORE each iteration of the
                    ADDER function.

                    A 32-bit pointer to the ADDER control structure will
                    be placed on the stack when the HeliOS BEFORE command
                    is called, so you must take care to clear the stack.

Adder_BeforeCode    This field, if non-null, contains a pointer to a machine
                    code routine which will be run BEFORE each iteration of
                    the ADDER function.

                    A 32-bit pointer to the ADDER control structure will
                    be placed in address register A0 when the BEFORE
                    command code is called.

Adder_AfterForth    This field, if non-null, contains the CFA af a HeliOS
                    command which will be run AFTER each iteration of the
                    ADDER function.

                    A 32-bit pointer to the ADDER control structure will
                    be placed on the stack when the HeliOS AFTER command
                    is called, so you must take care to clear the stack.

Adder_AfterCode     This field, if non-null, contains a pointer to a machine
                    code routine which will be run AFTER each iteration of
                    the ADDER function.

                    A 32-bit pointer to the ADDER control structure will
                    be placed in address register A0 when the AFTER command
                    code is called.

Adder_Flags         This field contains the ADDER function control flags.

                    The following function control flags are available:

                    Any +ve number = Incremental ADD including stored results

                                     In this mode the stored results of the
                                     previous ADDER operation are recovered
                                     and used as the basis for a further
                                     ADDER operation, then stored again, and
                                     so on..... In other words there is an
                                     accumulative process with the results
                                     stored and reused each time.

                    0              = Skip ADDER function

                                     The ADDER operation is skipped, but the
                                     "Before" functions are still carried
                                     out as usual.

                    -1             = Simple ADD ignoring stored results

                                     In this mode the stored results of the
                                     previous ADDER operation are not used
                                     as a basis for the new ADDER operation.
                                     Instead the ADDER works from an initial
                                     null value, generating a new value with
                                     each iteration.  In other words this is
                                     not an accumulative process and the
                                     results are regenerated anew and stored
                                     for each iteration.

                    -2             = No ADD, but use 0 as final output values

                                     This mode simply generates "0" final
                                     values.

                    -3             = SelfRemove at once

                                     Self explanatory!

                    N.B.

                    "Before" functions still run in "Skip" mode.

Adder_CountDown     Sets up a CountDown, so that after the number of "ticks"
                    specified in this field the CDFlags value will be stored
                    into the Flags field of the ADDER command structure.

                    This function is switched off after each CountDown.

Adder_CDFlags       If a CountDown is being done, the value in this field
                    will be placed in the "Flags" field of the ADDER
                    command structure when the CountDown is complete.

Adder_CDForth       This field contains either null or the CFA of a HeliOS
                    function which you wish to be executed after CountDown
                    has completed.

Adder_CDCode        This field contains either null or a pointer to a machine
                    code routine which you wish to be executed after the
                    CountDown has completed.

Adder_SkipTimer     This field is used to store the internal timer status
                    of the ADDER motor.

Adder_SkipCount     This value gives the time delay between each iteration
                    of the ADDER function.  The ADDER will skip however
                    many "ticks" are specified here between each active
                    cycle.

                    A SkipCount value of "0" gives full speed operation.

Adder_ID            This MUST be set to "0", to identify the ADDER function.

Adder_AddCount      The number of data items constituting this ADDER.

Adder_AddData       A pointer to the start of the sequence of sub-ADDER data
                    structures associated with this master ADDER control
                    structure.

                    The sub-ADDER data structures, which are defined below,
                    are each placed sequentially in memory.

                    Each master ADDER control structure can drive an
                    unlimited number of individual sub-ADDERs, each of
                    which has its own data structure.

                    The series of sub-ADDERS performs a set of sequential
                    additions to generate one final pair of results for each
                    master ADDER.

                    The pair of final results can be stored in any number
                    of specified target locations (see below).

Adder_StoreCount    The number of storage locations filled by this ADDER.

Adder_StoreData     A pointer to the start of the sequence of ADDER storage
                    data structures.

                    Each master ADDER control structure can drive an
                    unlimited number of individual sub-ADDERs, and the
                    result pair from the whole series of additions can
                    be copied into an unlimited number of store locations.

                    Each of the target storage locations is specified by
                    one of ADDER storage data structures.

Adder_UserDataPtr   This is a "free" field which you can use as you wish.
Adder_UserData1     This is a "free" field which you can use as you wish.
Adder_UserData2     This is a "free" field which you can use as you wish.
Adder_UserData3     This is a "free" field which you can use as you wish.
Adder_UserData4     This is a "free" field which you can use as you wish.
Adder_UserData5     This is a "free" field which you can use as you wish.
Adder_UserData6     This is a "free" field which you can use as you wish.
Adder_UserStatus    This is a "free" field which you can use as you wish.


-------------------
AdderData structure
-------------------

AdderData_AddX(w)      = Value to add/subtract
AdderData_AddXPtr(l)   = Pointer to optional additional value to add/subtract
AdderData_ModX(w)      = Modifier - How many times to add/subtract
AdderData_AddY(w)      = Value to add/subtract
AdderData_AddYPtr(l)   = Pointer to optional additional value to add/subtract
AdderData_ModY(w)      = Modifier - How many times to add/subtract

Here is an amplified description of each field:

AdderData_AddX(w)      This field species a number to be used as the basic
                       X-value addition value. This is always treated as a
                       16-bit unsigned number, and sign must be specified
                       using the AdderData_ModX field (see below).

AdderData_AddXPtr(l)   This field, if non-null, specifies a pointer to a
                       memory location which contains an unsigned 16-bit
                       number which will be added to the basic ADDER value
                       specified in the AdderData_AddX field.

AdderData_ModX(w)      This field specifies how many times the value
                       obtained from the previous two fields will be added
                       or subtracted.  If the value of AdderData_ModX is
                       positive the operation will be an addition, and if
                       it is negative the operation will be a subtraction.

                       The operation specified here is a simple sequential
                       multiple addition or subtraction, and can be used if
                       required as a primitive multiplication function.

AdderData_AddY(w)      This field species a number to be used as the basic
                       Y-value addition value. This is always treated as a
                       16-bit unsigned number, and sign must be specified
                       using the AdderData_ModY field (see below).

AdderData_AddYPtr(l)   This field, if non-null, specifies a pointer to a
                       memory location which contains an unsigned 16-bit
                       number which will be added to the basic ADDER value
                       specified in the AdderData_AddY field.

AdderData_ModY(w)      This field specifies how many times the value
                       obtained from the previous two fields will be added
                       or subtracted.  If the value of AdderData_ModY is
                       positive the operation will be an addition, and if
                       it is negative the operation will be a subtraction.

                       The operation specified here is a simple sequential
                       multiple addition or subtraction, and can be used if
                       required as a primitive multiplication function.

--------------------
AdderStore structure
--------------------

AdderStore_StoreX(l)   = Pointer to a storage location for the X result.
AdderStore_StoreY(l)   = Pointer to a storage location for the Y result.

Here is an amplified description of each field:

AdderStore_StoreX(l)   This field contains a pointer to one location where
                       you would like the results of the ADDER X operation
                       to be stored.

                       Since you can have as many AdderStore structures as
                       you like, you can specify many locations to store
                       ADDER results by using more ADDER stores.

AdderStore_StoreY(l)   This field contains a pointer to one location where
                       you would like the results of the ADDER Y operation
                       to be stored.

                       Since you can have as many AdderStore structures as
                       you like, you can specify many locations to store
                       ADDER results by using more ADDER stores.

**********************************
HeliOS ADDER control command words
**********************************

There are NO words specifically to control ADDER functions.

All control is via the data structures detailed above.

ADDERs are started by using the expression:

  MyAdder INSTALLMOTOR

ADDERs are stopped by using the expression:

  MyAdder REMOVEMOTOR


************
Using ADDERs
************

ADDERs are VERY easy to use and to set up.

First you need to allocate a master ADDER structure:

    Adder_SIZEOF MAKESTRUCTURE  MyAdder D!

or something similar......

Then you need to allocate at least one ADDER data structure:

    AdderData_SIZEOF MAKESTRUCTURE MyAdderData D!

Then you need to allocate at least one ADDER store data structure:

    AdderStore_SIZEOF MAKESTRUCTURE MyAdderStore D!

Then you must set up the pointers and data structure values:

    MyAdderData  D@  MyAdder D@ Adder_AddData   INDEXD!L
    MyAdderStore D@  MyAdder D@ Adder_StoreData INDEXD!L

    MyAdder D@ SETSTRUCTURE1

    1    Adder_AddCount   STRUCTURE1  !L
    1    Adder_StoreCount STRUCTURE1  !L
    1    Adder_SkipCount  STRUCTURE1  !L
    1    Adder_Flags      STRUCTURE1  !L
    0    Adder_ID         STRUCTURE1  !L

This has set up the fundamental ADDER operation to work with just one ADDER
data structure and just one ADDER store location.

The value of "1" in "Adder_Flags" means that we will have an incremental
addition.

Here is how we might now set up the ADDER function which takes values in
AdderXIncrement and AdderYIncrement variables and adds them 5 times to
the base value during each adder operation:

 1 VARIABLEL AdderXIncrement
 2 VARIABLEL AdderYIncrement

 0                MyAdderData D@  AdderData_AddX    INDEX!L
 AdderXIncrement  MyAdderData D@  AdderData_AddXPtr INDEXD!L
 5                MyAdderData D@  AdderData_ModX    INDEX!L

 0                MyAdderData D@  AdderData_AddY    INDEX!L
 AdderYIncrement  MyAdderData D@  AdderData_AddYPtr INDEXD!L
 5                MyAdderData D@  AdderData_ModY    INDEX!L

The "0" values for AddX and AddY mean that these components of the addition
are ignored in this case.

If we represent the result store value of an ADDER operation as X-Result, we
have the following formula for this operation:

 X-Result = X-Result + (5 x AdderXIncrement)

Here is how we might now set up the ADDER stores:

 0 VARIABLEL AdderXStore
 0 VARIABLEL AdderYStore

 AdderXStore  MyAdderStore D@  AdderStore_StoreX INDEXD!L
 AdderYStore  MyAdderStore D@  AdderStore_StoreY INDEXD!L

In this case the result of each ADDER operation would be copied into the
AdderStore variables.

Then you must use INSTALLMOTOR when you want to start the ADDER process:

    MyADDER D@ INSTALLMOTOR

...and REMOVEMOTOR when you want to stop the ADDER process:

    MyADDER D@ REMOVEMOTOR

*********************************************************************
End
*********************************************************************
