beyond monolithic code . . .
Don Pomplun
Posts: 116
Haven't been on the forum in a looongtime. My only project worthy of Propellerism has been as my house controller. Originally written as one big monolithic piece of code (3 cogs, but no objects), it's become too cumbersome to modify . . .
So I'm going to modularize it. But I'm already running into "issues". Problem (first) is having a serial LCD alpha display that wants to be written to by different methods. If all are in the same cog, or different cogs in the same object, no problem. Here's a compacted example: [Don]
**************************** 2 cogs, 1 object - OK ***************************************
{
This initializes the serial object in cog 0.
The string sent from Aux in cog 1 works OK & the LED lights.
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long AuxStack[30]
OBJ
ser : "fullduplexserial"
PUB Start
dira[4]~~ ' RS422 hardware direction control
outa[4]~~
dira[16]~~ ' diagnostic LED pin
if ser.start( 5,3,2,9600 ) == -1 ' RS422 port for LCD screen
abort
cognew( Aux, @AuxStack )
repeat
PUB Aux
dira[16]~~ ' each cog needs to set direction of I/O
outa[16]~~ ' turn on test LED
ser.str( @Teststr )
repeat
DAT
Teststr byte "test 1 2 3 4",0
************************************************************************************
**************************** 2 cogs in 2 objects - NG ***************************
{
This initializes the serial object in cog 0.
The aux method is started in anothercog in another object (Test5).
When run, the aux method lights the LED, but no string prints.
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long AuxStack[30]
OBJ
ser : "fullduplexserial"
NextCog : "test5"
PUB Start
dira[4]~~ ' RS422 direction control
outa[4]~~
dira[16]~~ ' diagnostic LED pin
if ser.start( 5,3,2,9600 ) == -1 ' RS422 port for LCD screen
abort
cognew( NextCog.aux, @AuxStack )
repeat
**********************************************************************
************************** additional object *******************************
OBJ
ser : "fullduplexserial"
{ need to put the OBJ reference in to satisfy the str call.
Don't want to run fullduplexserial's Start method because
it would start yet another cog.
PUB Aux
dira[4]~~ ' RS422 direction control
outa[4]~~
dira[16]~~ ' each cog needs to set direction of I/O
outa[16]~~ ' turn on test LED
ser.str( @Teststr )
repeat
DAT
Teststr byte "test 1 2 3 4",0
TIA,
Don
So I'm going to modularize it. But I'm already running into "issues". Problem (first) is having a serial LCD alpha display that wants to be written to by different methods. If all are in the same cog, or different cogs in the same object, no problem. Here's a compacted example: [Don]
**************************** 2 cogs, 1 object - OK ***************************************
{
This initializes the serial object in cog 0.
The string sent from Aux in cog 1 works OK & the LED lights.
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long AuxStack[30]
OBJ
ser : "fullduplexserial"
PUB Start
dira[4]~~ ' RS422 hardware direction control
outa[4]~~
dira[16]~~ ' diagnostic LED pin
if ser.start( 5,3,2,9600 ) == -1 ' RS422 port for LCD screen
abort
cognew( Aux, @AuxStack )
repeat
PUB Aux
dira[16]~~ ' each cog needs to set direction of I/O
outa[16]~~ ' turn on test LED
ser.str( @Teststr )
repeat
DAT
Teststr byte "test 1 2 3 4",0
************************************************************************************
**************************** 2 cogs in 2 objects - NG ***************************
{
This initializes the serial object in cog 0.
The aux method is started in anothercog in another object (Test5).
When run, the aux method lights the LED, but no string prints.
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long AuxStack[30]
OBJ
ser : "fullduplexserial"
NextCog : "test5"
PUB Start
dira[4]~~ ' RS422 direction control
outa[4]~~
dira[16]~~ ' diagnostic LED pin
if ser.start( 5,3,2,9600 ) == -1 ' RS422 port for LCD screen
abort
cognew( NextCog.aux, @AuxStack )
repeat
**********************************************************************
************************** additional object *******************************
OBJ
ser : "fullduplexserial"
{ need to put the OBJ reference in to satisfy the str call.
Don't want to run fullduplexserial's Start method because
it would start yet another cog.
PUB Aux
dira[4]~~ ' RS422 direction control
outa[4]~~
dira[16]~~ ' each cog needs to set direction of I/O
outa[16]~~ ' turn on test LED
ser.str( @Teststr )
repeat
DAT
Teststr byte "test 1 2 3 4",0
TIA,
Don
Comments
. . . and thanx Phil -- looked fine when I pasted it, and didn't Preview. Good thing it wasn't very complicated code with multi-multi-multi indents ;=)
Don
There is one cog reading the buffer and comparing it with the content of the last transmitted buffer-content. If something has changed transmitt buffer-content new.
all other methods just write into the buffer. The buffer is an array of bytes where each bytes represents a character on the display including the position on the display.
In this way multiple methods from anywhere can write towards the display but just write into the buffer. Then the LCD-sendbuffer-cog sends the characters really to the display.
keep the questions coming
best regards
Stefan
On the suggestion about the buffer, where would I put the buffer so it could be accessed from all objects?
TIA
Don
After a little pseudocoding, I conclude that
a. items declared in a VAR block are global to all methods in an object (no matter how many VAR blocks are declared - probably bad form anyway).
b. items declared in a DAT block are global to all objects in an app (cog association is irrelevant)
That seems to mesh with your statements. Will pursue that approach.
thanx,
Don
Items declared in a VAR block are global to all methods in an object, but there's a separate instance of all VAR items for each use of the object in an OBJ declaration in the program. When a method of the object is called, the method uses the particular instance of the VAR items associated with the object name used as a prefix for the method.
Items declared in a DAT block are global to all methods in an object and there's a single instance of the DAT items common to all declarations of the object in the program.
Combining some of the suggestions made, I decided to try having my display interface declare a screen buffer in a DAT block. Since I have cogs-a-plenty, one would just keep reading the DAT buffer area and refresh the display contniuously. Worked fine until I tried sending data to that block from another object. Whops . . . Reread Mike's comments and realized that the DAT block isn't accessible outside an object. Bummer.
Next attempt is sending a set of params (line, col, string) from other object/methods. Beginning to seem over-complicated just to gain object aloofness. Since I've NEVER reused any of my old code ;=) maybe this isn't worth the effort. I can write it all as one big document, like before, but break up my VAR into multiple chunks, geographically located with their respective methods. Same for DAT blocks.
Not discouraged; just don't want this project to become and end-of-life issue ;=)
[lamenting hitting my medicare b'day]
Don
Do DAT blocks go in Propeller "main memory"? If I declare an area in DAT in one object (like the buffer the object uses to write to the display), I'm not sure how to write into that same area from another object. I can't just declare a DAT block in obj#2 and expect it to be the same space. Do I somehow pass the address of the DAT from obj#1 to obj#2, and then use offsets in #2 to put data in the table?
TIA
Don
. . . so if I want to access a DAT area defined in one object from another object, how do I find it?
in my top object I have a declared array, X, in its DAT block. I can pass its address to another object as @X.
In that subsidiary object I can use Byte or ByteMove to put stuff in the top's array.
But can I declare an array in the subsidiary object that will start at X's address so that I can easily reference this common area with normal subscripts without a lot of address machinations?
TIA
Don