Sharing variables between COGS
electric550
Posts: 122
I thought I saw an example program of two cogs sharing variables through the central hub...but I cannot find it now...could someone point me to an example of two cogs sharing data between the two? Or post some code of this nature? for example cog A send value Z to cog B then CogB sends back value x to CogA?
I have read that cog A would send a value to the hub memory then cog B would read that value and vice verse but I am having trouble figuring it out.
Any help is appreciated
I have read that cog A would send a value to the hub memory then cog B would read that value and vice verse but I am having trouble figuring it out.
Any help is appreciated
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Basic Stamp,···· Propeller,·· · SX,·· FUN!
START:·
>Proccessing Data. . . .··
>Task Complete. . .·.
>Saving Data. . . .
>Entering SLEEP Mode. . . .
>Signing OFF
Post Edited (ProcessingData...) : 4/18/2009 1:44:56 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
Two cogs can communicate most easily using RDxxxx/WRxxxx instructions that access the same hub memory locations. The main issue is that the cogs have to communicate in such a way that they don't "mess each other up" by one cog changing a memory location while the other cog expects that the location won't be changed. For example, if you have two cogs, each with the statement "X := X + 1", this will sometimes work and sometimes it won't. If cog "A" starts this statement at time 1 and cog "B" starts the identical statement at time 2, cog "A" will fetch "X", add 1 to it, and store the result back into "X". At time 2, cog "B" will fetch "X", add 1 to it and store the result back into "X". Unfortunately, cog "A" will have stored its updated "X" while cog "B" is still adding 1 to it. Cog "B" will store its updated value right on top of the value just stored by the "A" cog. Instead of "X" being increment by 2, it's only incremented by 1.
There are ways around this. The simplest is to use the LOCKxxx instructions to force one cog to wait until the other cog is done with its update. The Propeller Manual has some examples of this.
With regards to Spin language, here are 2 examles how to pass variables between cogs.
CogObjectExample is from the PE Kit. It repeats each time and restarts Blinker with the current "time" variable. Nothing fancy there.
CogObjectExample2 is my version to have Blinker2 start once and run until the 20 reps are done, rec'ving the current "time" in the process.
Hopefully this helps, and furthermore, I believe the PE examples are where you saw the various ways cogs can communicate.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Bad spellers of the world untie!
RDLONG var[noparse][[/noparse]0], @500
is this correct?
below is what led me to assume this
DAT
org 'reset address pointer
Loop rdlong t1, par WZ 'wait for command
if_z jmp #Loop 'jump of zero
movd :arg, #arg0 'get 8 arguments
:arg mov t2, t1
RDLONG
Instruction: Read long of main memory.
RDLONG Value, 〈#〉 Address
Result: Long is stored in Value.
• Value (d-field) is the register to store the long value into.
• Address (s-field) is a register or a 9-bit literalwhose value is the main memory address
to read from.
–INSTR– ZCRI –CON– –DEST– –SRC– Z Result C Result Result Clocks
000010 001i 1111 ddddddddd sssssssss Result = 0 --- Written 7..22
Explanation
RDLONG syncs to the Hub, reads the long of main memory at Address, and stores it into the
Value register.
If the WZ effect is specified, the Z flag will be set (1) if the value read from main memory is
zero. The value from main memory will be written to Value unless the NR effect is specified.
RDLONG is a Hub instruction. Hub instructions require 7 to 22 clock cycles to execute
depending on the relation between the cog’s hub access window and the instruction’s moment
of execution. See Hub on page 24 for more information.
var[noparse][[/noparse] 0 ] doesn't mean anything in an assembly instruction.
WRLONG
Instruction: Write a long to main memory.
WRLONG Value, 〈#〉 Address
• Value (d-field) is the register containing the 32-bit value to write to main memory.
• Address (s-field) is a register or a 9-bit literal whose value is the main memory
address to write to.
–INSTR– ZCRI –CON– –DEST– –SRC– Z Result C Result Result Clocks
000010 000i 1111 ddddddddd sssssssss --- --- Not Written 7..22
Explanation
WRLONG synchronizes to the Hub and writes the long in Value to main memory at Address.
WRLONG is a Hub instruction. Hub instructions require 7 to 22 clock cycles to execute
depending on the relation between the cog’s hub access window and the instruction’s moment
of execution. Hub on page 24 for more information.
Do keep in mind that $10 is hexadecimal while 500 is decimal.
Post Edited (Mike Green) : 4/18/2009 4:06:40 AM GMT
cognew(WriteMain(10,500), @stack[noparse][[/noparse]0])
cognew(ReadMain(10,500),@stack[noparse][[/noparse]10])
PUB WriteMain(cogaddress,hubaddress)
dat
MOVS 10, #$30
WRBYTE 10,500
PUB ReadMain(cogaddress,hubaddress)
serial.start(31,30,0,9600)
repeat
cog := BYTE[noparse][[/noparse]0][noparse][[/noparse]500]
serial.tx(cog)
dat
RDBYTE 10,500
Theoretically it should send zeros out the serial port
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
Pub RAM1
cognew(@assemble,@stack[noparse][[/noparse]0]) 'Start cog to pass through the servos
cognew(Prog1,@stack[noparse][[/noparse]10]) 'Start cog for program to read pwm values
PUB Prog1
text.start(31,30,0,115200)
repeat
text.rx(pulseWidths[noparse][[/noparse]0])
if pulseWidths[noparse][[/noparse]0] > 2000
BYTEFILL(500,1,0) 'if 1 from serial port write 1 to ram location 500 in hub
outa[noparse][[/noparse]7] := 0 'turn on LED --it is active low
else
outa[noparse][[/noparse]7] := 1 'turn off LED --it is active low
BYTEFILL(500,0,0) 'if 0 from serial port write 0 to ram location 500 in hub
waitcnt (counter)
DAT
org
assemble
mov dira, mask 'intialized pins
mov 50, $0
loop RDLONG 50, #500 'reads value from hub address 500??? and stores into 50??
TJZ 50, #loop
movd outa, ina 'mov pins 0 to 8 to pins 10
jmp #loop
mask long %00000000_00000000_11111111_10000000
comp byte %00000000
2) The "mov 50,$0" isn't necessary since location 50 is immediately changed using the RDLONG.
3) The "outa[noparse][[/noparse] 7 ]" in Prog1 won't do what you expect since I/O pin 7 (in that cog) is in input mode. Each cog has its own private copy of DIRA and OUTA and changes to either are internal to that cog only. All of the DIRA and OUTA bits are combined as shown in the Propeller Manual to produce one I/O pin value for each bit. Look at that diagram for details.
4) You have no idea what's contained in locations 500 to 503. The RDLONG reads 4 bytes starting at the address given. If you want to use only one byte, use RDBYTE instead. Location 500 might be somewhere in your program or in the stack space or variable space. It's generally not a good idea to use numeric addresses in the hub (shared) memory for that reason. It's easier to use PAR, so you'd have "RDBYTE 50,PAR". The COGNEW would then be "COGNEW(@assemble,@variable)" where "variable" is an ordinary byte variable in your program. You wouldn't need to use BYTEFILL. You could just write "variable := 0" or "variable := 1".
5) Look at the examples for serial input. "text.rx(pulseWidths[noparse][[/noparse] 0 ])" doesn't mean anything and wouldn't compile anyway.
did you look into the Machine Language Tutorial
from DeSilva ?
and the Assembly, step by step
from Graham Stabler
best regards
Stefan