Scope of variables for shared (or duplicate?) objects
Erlend
Posts: 612
My Main calls an object which manages a set of devices on a bus, which again calls a number of objects for each type & instance of devices (so far MCP2301 and VL6180), each of which calls an I2C object to do the work reading and writing to the individual devices (two MCP's and three VL's) connected to the bus.
In my mind the elegant way would be for the bus manager object to assign scl and sda pins and reset the bus, so that the device object happily ever after did not need to concern about the slc and sda pin definition. But that won't work (?) they need to call their I2C objects at least once with slc and sda to set that definition - or provide those parameters each call.
As far as I can see there will be many instances of the I2C object in this scheme, each caring for its own variables (even though the compiler probably makes sure there is only one set of object code).
Am I right?
I would like to keep the structure where there is one object (=non standard) managing the specific set of bus'ed devices, one object (=half standard) for each specific type of device, and the the I2C object (full standard) at the lowest level.
What would be the elegant way of managing slc and sda pin variable initiation?
Erlend
(code is not ready)
In my mind the elegant way would be for the bus manager object to assign scl and sda pins and reset the bus, so that the device object happily ever after did not need to concern about the slc and sda pin definition. But that won't work (?) they need to call their I2C objects at least once with slc and sda to set that definition - or provide those parameters each call.
As far as I can see there will be many instances of the I2C object in this scheme, each caring for its own variables (even though the compiler probably makes sure there is only one set of object code).
Am I right?
I would like to keep the structure where there is one object (=non standard) managing the specific set of bus'ed devices, one object (=half standard) for each specific type of device, and the the I2C object (full standard) at the lowest level.
What would be the elegant way of managing slc and sda pin variable initiation?
Erlend
(code is not ready)
Comments
I know nothing of I2C but I think you need a different architecture.
1) For any give device or bus (I2C) connected to a particular bunch of pins there should only be one COG accessing those pins. Otherwise you are going to get into a mess. That COG will probably be running code from a single object. That is your "bus manager" or low level driver.
2) Any application level code that needs to access that device/bus should do so via a "mailbox" in memory through which messages are passed issuing commands and collecting results.
3) The address of that mailbox can be passed around to any other code that needs to talk to the bus.
4) Probably want to use locks around access to that mailbox to avoid race conditions.
That is to say, instead of thinking about calling some methods on some object and having multiple instances of that object, send messages to a single instance instead.
The information about the pins and global variables have to make its way all the way down from the Main and to the I2C for this to work. The DeviceManager could pass that as part of the call each time it orchestrates a poll of devices on the bus, or maybe it can be done once and for all as part of the Initiate routine?
This is an outline of the DeviceManager.
Erlend
But more to the subject at hand, I think you need to refactor your code. There is no reason for more than one object to know which pins are scl and sda, and that should be the only object that controls the I2C bus.
-Phil
The lrf.init() and dio.init() are not intended to create new instances, they are just calls to library functions. I could as well have put them in this code as PRIV methods, but want to avoid that because of overall software management considerations (they should be in the Library). Therefore lrf[n] is not applicable, right?
Erlend
-Phil
A "method" is one of the functions within a object (Spin file). Those PUBs and PRIs
An instance is a particular incarnation of an object create by an entry in a OBJ section of some parent onject instance.
Instances of a particular object all have their own separate memory spaces for all the variables in the objects VAR.
Instances of a particular object all share the same DAT section data of the object.
Ah- so if I put the pin numbers for slc and sda into DAT variables of (e.g. the i2C) object then it sticks? Means I could let the DeviceManager do it by calling a method in busI2C which sets up the DATs and then thereafter any calls to bus r/w methods in BusI2C would not need to include the pin numbers as parameters? That would be magic.
Erlend
EDIT:
Even when DeviceManager has -and then both the MCP and the VL also include
-still the magic applies?
Erlend
Yes. There is only one DAT section for all the instances of the same object at run time.
So if yo do:
someObjectInstance1.init(someParameter, otherParameter)
from one place at start up and those parameters are saved in a DAT section. Then you can do:
someOjectInstance1.doSomething()
or:
someObjectInstance2.doSometing()
from anywhere in the application and those same saved DAT values will apply everywhere for use by "doSomething"
Now, one issue is that if you have those different instances running in different COGs and those parameters select pins you need to ensure that DIRA is set correctly in all of them. Every COG has it's own DIRA register. You also need to insure that those instances don't try to use the pins at the same time during read/write calls.
All in all I would only have one object instance running on one COG handling the pins for one bus or device. Then arrange for any other part of the application to use that device by sending messages to that device handler.
Of course those messages can be sent by having an interface object to the driver object that can be used from anywhere and uses it's common DAT areas as a message bus in memory.
Once the Init procedures are done, all the bus-polling takes place in one cog, the one created by DeviceManager. There is no need for more.
Using DAT as a message bus in memory I have to think a bit more about, I do not fully grasp the possibilities of that.
Erlend