An object is any file with a .spin extension that contains comments, data, and executable Spin code and serves as an encapsulation of that data and the methods to operate on it. A Propeller Application is made up of one or more objects. An object may be designed to achieve the goals of the whole application by itself, or it may only focus on a small portion, and be included by another object as part of a larger application. An application’s top object is where execution begins.
Spin embraces the modular programming paradigm of objects as "devices" that can be collected together in an application, each doing their part to achieve a larger goal. This is similar in concept to that of object-oriented languages, however, aspects of inheritance and polymorphism, commonly considered to be integral parts of object-oriented languages, are not supported by Spin. For this reason, Spin is often called "object-based" rather than "object-oriented."
Spin objects are built from six special-purpose blocks: CON, VAR, OBJ, PUB, PRI, and DAT. CON and VAR are for declaring constants and variables, respectively. OBJ is used to declare what other objects will be used during this object's execution. PUB and PRI declare public and private methods, which contain the executable Spin instructions. DAT blocks contain data and/or Propeller Assembly programs.
A top object is simply the first object in the Propeller Application; code execution begins at the first public method in the top object. It is called the "top" object because it determines what "building block" objects are also included in the application "beneath" it. The top object also configures initial global settings for the application, such as the clock speed, and is usually the object that "lives" for the entire length of time the application is running. Every Propeller Application has one, and only one, top object.
Most objects are building block objects; they are simply the objects meant for use by other objects. An application's top object often requires one or more building block objects, each of which may themselves require one or more building block objects.
Building block objects are designed to perform a specific task, such as retrieving data from a sensor, performing complex math calculations, or sending information to a display. Such building block objects are usually not complete applications on their own, nor are they designed for only one particular application, but are meant to be re-usable in any application that needs the specific task performed.
A building block object has public methods that serve as the interface though which other objects interact with it. By convention, building block objects that require configuration, or that need to start and stop cogs as a result of their use, typically have an Init, and/or Start and Stop methods for this purpose. Note that a building block object can also be a top object, but most are not written for this purpose.
By convention, building block objects that do not to launch (and later terminate) another cog do not include Start and Stop methods.
Yes, there is a "reference" limit of 255 per object.
For each individual object, the number of methods plus the number of included objects in its OBJ block cannot exceed 255.
Reference Limit Per Object: Method Count + Object Count ≤ 255
Examples:
Note that this limit applies to each object individually. For a parent object, each included child object only counts as "1" towards this limit, regardless of how many methods or objects that child object uses. So, even if an object has reached its limit of 255 combined methods and included objects, it itself can be included by another object without error because that parent object has its own limit of 255 combined methods and included objects.
Method names and the purposes they serve are entirely the choice of the developer, but following certain conventions is recommended for methods that serve the roles of object configuration (Init) and cog management (Start and Stop).
These conventions serve a familiar "getting started" purpose to new users of the object.
By convention, developers name a method "Start" when it serves as the cog launch manager of a building block object. An object with a Start method should also have a Stop method, and occasionally an Init method as well.
Similarly, developers name a method "Stop" when it serves as the cog termination manager of a building block object. An object with a Stop method should also have a Start method, and occasionally an Init method as well.
Example Start and Stop Methods:
VAR byte Cog 'Cog (ID+1) that is started by this object
PUB Start({ParamaterList}): Success
{Launch another cog for parallel processing}
Stop
Success := (Cog := cognew({SpinMethodOrAsmAddr}, {StackAddrOrPARValue}) + 1) > 0
PUB Stop
{Terminate managed cog, if any}
if Cog
cogstop(Cog~ -1)
In this example, the Start method calls Stop to terminate any previously started cog (in case Start gets called multiple times) and then launches a new cog with COGNEW. It stores the Cog ID returned by COGNEW, plus 1, into the Cog variable to record the cog-launch status and simplify decision logic in Stop. It uses a comparison operation (> 0) to set the Success result variable to True if a cog was started; False otherwise.
The Stop method checks if the Cog variable is True (any non-zero value), and if so, terminates the cog that this object had started. The expression Cog~ -1 first subtracts 1 from Cog (delivering to COGSTOP the exact ID of the cog that was launched) then clears Cog to 0 (False) so successive calls to Stop don't inadvertently terminate innocent cogs.
By convention, developers name a method "Stop" when it serves as the cog termination manager of a building block object. An object with a Stop method should also have a Start method, and occasionally an Init method as well.
By convention developers name a method "Init" (short for "initial" or "initialization") when it serves as the configuration method of a building block object. An object with an Init method may or may not also include Start and Stop methods.
Often developers will name the first method of a top object "Main" because it serves as the application starting point and the highest-level coordinator of application function.
Main is not a reserved word in Spin; special status is given only to the first public method in the top object of a Propeller Application.
No. By convention, building block objects that do not need configuration do not include an Init method, and those that do not need to launch (and later terminate) another cog do not include Start and Stop methods.
No. There is no direct relationship between objects and cogs. Applications are limited by the size of the Propeller chip’s Main RAM, which is 32 KB (kilobytes) and not by the number of object files that make up the application. An application may consist of a single object, or many objects, as long as the total size of the application is less than 32 KB. An application, whether made from one object or many objects, may execute with one, two, or up to eight cogs depending only on the collective objects' "requests" to launch cogs.
Objects describe how to get tasks done and cogs perform those tasks. Since an object encapsulates all the knowledge necessary to achieve the given task, it is up to the object to decide when and how many other cogs should perform the task. In this way, objects are the natural manager of their own cogs, starting and stopping one or more other cogs as necessary for the given task.
It is possible for any cog to start and stop any other cog, but in practice it is not done outside of the logical object except in extreme cases.
Yes. In an object's OBJ block, the declaration of a subobject can use array syntax to specify multiple instances of that object, like the following:
OBJ
Ind[2] : "Inductor"
Here, the Inductor object's nickname, Ind, is specified as being an array of 2 such objects and can later be accessed as Ind[0] and Ind[1].
In this case, at compile time the application image is built with two copies of Inductor's VAR and OBJ blocks so that each instance (Ind[0] and Ind[1]) has its own global variable memory and subobjects. However, each instance uses the same code and data; PUB, PRI, and DAT blocks.
Object instance creation and destruction requires the allocation and release of memory. In a Propeller Application, all object instances are statically defined at compile time and never destroyed at runtime, producing a static allocation of memory. This is advantageous in a real-time system because it keeps execution timing consistent, whereas dynamic creation and destruction of objects at runtime leads to indeterminate situations like the occasional need for memory garbage collection.
Propeller P8X32A Questions & Answers
Copyright © Parallax Inc., dba Parallax Semiconductor
Version 1.3.1
10/23/2013