INA & OUTA control
JBWolf
Posts: 405
I'm having trouble launching 2 cogs that each monitor a set of pins with pushbuttons on them.
In one cog it monitors the 2 input pins and flashes an LED if one is pressed.
The other cog increments or decrements variables depending on which button is pressed.
In the beginning of each PUB being launched I have declared the pins and variables before use.
But as soon as I launch the second cog, it stops working
This is in each method being launched:
dira[20..21]~ ' Set Buttons to input
outa[20..21]~
dira[LED]~~ 'used in cog2 only
In cog 1 I am basically using this:
repeat
if ina[20] == 1
value := ++ value
In cog 2 I am using this:
repeat
if ina[20] == 1
outa[LED]~~
In one cog it monitors the 2 input pins and flashes an LED if one is pressed.
The other cog increments or decrements variables depending on which button is pressed.
In the beginning of each PUB being launched I have declared the pins and variables before use.
But as soon as I launch the second cog, it stops working
This is in each method being launched:
dira[20..21]~ ' Set Buttons to input
outa[20..21]~
dira[LED]~~ 'used in cog2 only
In cog 1 I am basically using this:
repeat
if ina[20] == 1
value := ++ value
In cog 2 I am using this:
repeat
if ina[20] == 1
outa[LED]~~
Comments
So if one COG sets DIRA as output that does not have any effect for the other COGS.
Every COG that wants to output on some pins must have it's own DIRA statement to set those pins to output.
Also every COG can write to the same pin for OUTA. The actual output on the pin will be the logical OR of what is written.
So basically if any COG sets a pin to 1 the output will be high.
As INA always works (even if the PIN is set to output it gives you the state of the PIN) it must be elsewhere.
Is LED maybe defined as PIN 20 as well?
Oh ... wait a minute:
When saying this is in each method do you really mean that you set the LED-Pin to output in both COGs? You should only define PINs as output in the COG that's really using it!
Check the manual, chapter 1, I/O PINS.
In revision 1.2 of the manual it is at page 26-27.
Massimo
Just out of curiosity (or I need to go back to the book) why does the code set the direction of 20/21 to input and then try to set those pins to low using an output statement? Will this value override the actual pin input?
Frank
With everything in place, nothing runs at all, looks like it locks up.
Still locks up if I remark out every 'outa[20..21]~'
I need 2 cogs to EACH control the same 2 buttons is whats really going on.
I have 2 LED's, one is for power, the other as a mode indicator.
If you press any button, it flashes the power LED just to show you it did recognize the button being pressed. Depending on which button is pressed, it will change the variable for turning the laser on or off.
So if you look in the PwrFlash method... this keeps the power light on and flashes if a button is being pressed.
In the LSRControl method, if button 1 is pressed, the laser variable gets turned to 0, which shuts off the laser. If button 2 is pressed, it will turn back on.
Seems to me there is a control conflict while using two INA[] statements in two different cogs.
Only thing I can think of doing is removing the PwrFlash method, using the Main method to initially turn on the power LED... then in the 'LSRControl' method, use !outa[PLED] with a delay, then another ! to turn it back on.
This way I could still get the flash while keeping all button and LED control in the same cog.
I would like to know how to receive button input from 2 different cogs at the same time
I think I might be able to get everything done I need to with the buttons in one cog... but it shure would be nice to be able to check a button status from another cog
Don't know if this is the only problem, but this is a bad idea:
cognew(LSRControl(@laser), @stack[4000])
The stack is only 4000 longs big. I think you are used to stacks in other microcontrollers, but the stack in the propeller does not grow top to bottom! It's bottom up!
So, in the code you posted you should subtract 1000 from each stack-pointer.
1000 longs is a very big stack. With 4000 longs you already used 4000*4 = 16kByte of RAM, which is half of the RAM available.
You don't need the DIRA~ and OUTA~ statements. All pins are per default inputs.
PUB PwrFlash
should only set pin 27 to output, as this is the only pin used by the function.
I would start with something smaller.. Take your code and just have 1 cog sampling the 2 input pins like you have. Have a second cog taking those hub variables and setting led(s). When this works, add another cog to take the hub variable and set the laser (presume you are ust using an led to indicate this for now). Build your code up with little cogs, one at a time. You will be amazed at how simple this seems, and any problems are so much easier to find. Otherwise, you are looking for a needle in a haystack, and of course there may be more than one needle!
I have now completed the program... but I was never able to use outa to the same pins from more than one cog.
A good example of this.... The 'Scan' method in the above code declares dira[8..11]~~ and uses those pins just one time with outa during what is remarked as 'calibrate'. I later tried in another cog a very VERY simple test by manually setting the next step for the outa[8..11] (made absolutely sure what the next step is and completely avoided using global or local variables to eliminate conflicts or incorrectly used longs). It absolutely will not go to the next proper step from another cog... I dont know if the last outa from the 'calibrate' is still active in that cog or what... but it is impossible to make a proper movement using outa[8..11] in another cog. I tried every single way I could think of. I'm betting it is caused because the outa[8..11] in the 'scan' method cog is still active until I turn it off with something like %0000... so the new cog is actively fighting the other cog as they are both trying to set outa[8..11] at the same time.
I believe the proper way to do this is to declare a new cog dedicated just to setting specific outa pins with global variables, then changing the global variable within other 'control' methods/cogs... rather than having a 'control' cog with the outa pin declarations inside it, this way it does not matter what cog is trying to use it because they are all writing to a global variable rather than raw outa[]. Or by only using outa in a 'control' method/cog that is 100% dedicated to those pins, no other methods or cogs can use those pins with outa
The way I did get it to work, each cog is dedicated to certain pins... no other cog will ever try to use them. Otherwise I get incredibly unpredictable results or a complete lockup.
I even came up with a very easy way to enter a menu system by pressing buttons, and if another button hasnt been pressed within 10 seconds of the last, it will exit the menu system... if a button is pressed, not only does it restart the 10 sec counter, it accurately records the button pressed.
The PE book only shows how to keep good timing by using a waitcnt and adding the current count to the clkfreq, then waiting for that to expire.
i.e. 1 second:
dT := clkfreq
T := cnt
waitcnt(dT + T)
++second
This will miss everything that has happened within that second.
To use this method, you would basically have to launch a 'clock' in a new cog, then retrieve the current time to compare against later... way too much work.
I'm not liking some of the basic principals of coding structure taught in the PE book.
It was a real AHA! moment when I figured out a way around this
With regard to the waitcnt, this just makes the core sit idle and consume little power while waiting for the count to expire. Nothing complex about this... it is doing nothing so cannot possibly see anything on pins. There are other ways to use cnt if you need to do other things while waiting. Dont forget to also look at waitpeq and waitpne too.
If you want to use the same PINs in different COGs you have to make sure that the active COG is taking over the last state of the inactive COG and then set OUTA to 0 in the inactive COG. This is what I did in a DMA-like driver ;o) I have a graphics display which of course needs to be filled with some graphics-data. When reading a picture from SD-card, I let the SD-card driver (FSRW) takeover the control of the display I/Os. This way it can simply send the data directly to the display.
Let's say you have a bus where different kind of devices are attached to, it could also make sense to have a central I/O controller COG which simly watches one or more HUB-RAM locations and send those values to the BUS. The drawback here is that it changes/slows down the timing constantly, whereas the takeover-concept only slows down for the takeover - which is very fast.
Hope you recognized this part of my previous post. It's very important!
With @stack[4000] you already point behind the stack variable, as the allowed indexes are 0 - 3999. So, with this cognew you immediately overwrite whatever is behind stack. In your example I'd guess that you overwrite the stack of the initial COG which is using all remaining HUB-RAM. Especially the return-address of the initial-COG is in danger in this case, as your cognews are running in a function. So, when the function is done, your initial COG can end up anywhere, doing nasty things.
For input it also might make sense to have a COG that watches the I-PINs and dispatch the input to different HUB-RAM locations. As already mentioned the waitpne can wait for any change of the input-PINs. If you press one button you set a flag here, if you receive an impulse coming from a key matrix you store the value in a input-ring-buffer .... whatever you need. Of course you can even to similar things as in common operating-systems like implementing a event queue ...
Be aware that there is a separate DIRA and OUTA register for each COG.
So if one COG sets DIRA as output that does not have any effect for the other COGS.
Every COG that wants to output on some pins must have it's own DIRA statement to set those pins to output.
Also every COG can write to the same pin for OUTA. The output on the actual pin will be the logical OR of what is written to OUTA registers by the various COGS involved.
So basically if any one COG sets a pin to 1, the output will be high even if all the others are setting the same pin to 0 (low).
Ah, if it is being OR'd, that would explain why I am getting such unpredictable results!
Thanks, I will check out waitpeq and waitpne
Mag:
you are directly contradicting cluso and heater, and are telling me something that I already tried and found not true. If I could simply have the new cog take over the last state, then why does it not work when I have the new cog outa the last state the other cog was in, and try to move to the next outa state?
I believe Cluso and Heater are right, it is being OR'd... I can confirm this later by taking the last cog1 state and do an OR calculation to see what the proper value for cog2 would be.
The PE book teaches the opposite of what you are telling me about the stack. Please see page# 73 in the PE textbook... it teaches to address stacks sequentially from lowest to highest. so cognew(method, @stack[100])... cognew(method, @stack[200]) and so on. This is the way I have used it and it works great right now... so I am not going to change it.
As for the stacks, it makes no difference what order you give stack blocks to COGs. Assumming the each block is big enough for the stack requirements of the COG it is given to.
However it is true that Spin uses stack from low to high as it runs. This is opposite to most processor stacks. Mostly when using Spin you neither need to know or care about that. BUT there is some code around that relies on the ordering of parameters and variables on the stack, lonesocks floating point object for example. That really is somewhat advanced stuff though, not to mention using the language in undocumented ways.
Depending on the hardware you attached, it might be necessary to do the takeover in several steps:
1. the COG that's going to be switched to inactive has to tell the other COG what the state is (via HUB-RAM/wrlong/rdlong or using a PIN as signal)
2. the active COG reads it (INA) and set's the OUTA accordingly
3. the active COG tells the inactive COG that it can "release" the outputs (again using HUB-RAM or a PIN)
4. now the active COG has full control and can change PINs as desired
Why? Because one output might be a clock signal. If the state before switch is 1 and the inactive COG releases the outputs before the active COG sets it to 1, there will be an unintended 1-0-1 transition on the clock line.
Of course there is a lot of hardware which does not need such a takeover. Each COG simply starts fresh again.
Again ... for the stacks ....
Please read the PE textbook again! If you have a stack defined having 400 longs:
long stack[400]
the indexes allowed to use are in the range 0 - 399
If you then start a COG with
cognew( dosomething, @stack[400] )
you definitely do something wrong! And depending on what the main cog is doing and what the new COG is doing, your program might fail sooner or later!
Have a closer look at the PE lesson. I'm sure it starts the first new COG with
cognew( do1, @stack[0] )
then cognew( do2, @stack[100] )
then cognew( do3, @stack[200] )
and finally cognew( do4, @stack[300] )
so that the 4th COG started can use stack[300] up to stack[399].
Maybe worth to mention: The COG which runs your Main program does not need an explicit stack. It's implicitly using the whole remaining memory (not occupied by SPIN, VAR, DAT) as it's stack. In your short program this stack starts directly behind your stack variable. The last buggy cognew which used an illegal stack-index definitely destroyed the stack of your Main. Maybe you did not see any effects because the Main ends in an endless loop anyway but maybe parts of your initial problem was just because of that.
Your right, I did miss the first cog being declared @stack[0].... but how does a @stack[300] know to use 300-399? is this because we are assuming the initial VAR stack is set at [400]? so if it was VAR'd at [1000] it would use 300-999?
How can you 'release' outputs in a cog that is still active? Is there a way to let it know that it will no longer be using certain pins and basically null the dira[pins] for that cog? Meaning no OR's will happen as that cog is no longer using an outa.
Or by releasing do you mean setting the outa in the cog to zeros, this way any outa's from a new cog will be OR'd and will still be the same value as the new outa.
I am starting to think in terms of dedicating a cog to declaring the actual outa[pins] and using globals, this way I can write as many methods as I would like and they can all access the same pins through a global variable.
Seems to me this will keep the OR comparisons to a minimum and very easy to manage.
Better not to funnel all your I/O through one COG. There is no problem using DIRA, INA,OUTA from each COG as intended and as everyone else does. Pushing eveeything through one COG will be more complex and slow and may not play well with all the existing objects out there yo may want to use.
In guess "releasing" the pins could be taken two ways.
1) Have the COG set DIRA bit to zero for those pins so that any other COG can use then as input or output.
2) Have the COG set the OUTA bits as zero so that any other COG can drive the output high as it likes, but cannot use as input in this case.
It's up to you but I think the former option is better in general.
399 is the max. index available for the last COG. But there is no check! If you call to much subfunctions within other subfunctions or use to much locale variables/parameters, nothing will avoid overwriting parts of the memory which is behind the stack! These are the funny bugs because anything unpredictable can happen.
A dedicated COG is ok if you can efford a COG not doing much more than that and if you can live with the drawback in speed. If your signals need a tight timing it might be difficult to meet that needs. And even there you have the question "How do you manage access to the variable?" As soon as more than 1 COG has to change bits in this variable you need to synchronize access to that variable.
I mean using one cog to control one logical group.... such as:
motor one pins [8..11] = cog 1
motor two pins [12..15] = cog2
led pins [20..21] = cog 3 and so on
This way they are all independent and easy to manipulate
One thing I am not sure about...
Lets say I do it this way and each cog has a global for 'enabling'...
So making one motor move can simply be done like this: MotorX := 2 'causes the X axis motor to move 2 steps.
And same with the other motor: MotorY := 3 ' causes the Y axis motor to move 3 steps
So how can I make motor X and motor Y move at the same time?
If I set one global at a time, then one will move before the other correct?
So can I do something like:
MotorX := 2 and MotorY := 3
So that it will set both variables at the SAME time?
No you cannot set two variables at the same time.
If the range of values of the two command variables is small enough to be represented in 16 bits then you can combine them both into a single LONG and write that in one go as the command for both motors.
With a single COG you can simply implement the bresnham algorithm for 2 "lines" and let one loop drive both motors.
But even then the problem remains. How would this driver know when setting motorX and motorY is consistently done? A very common way in different drivers is that they have a command/parameter structure somewhere in HUB-RAM. In your case you'd need 1 variable for the command and 2 variables for the parameters. First the program that wants the motors to move would set both parameters. Then it sets the command variable to CMD_MOVE (for example =1) - this is a constant you'd define in the driver-object. When the driver is done with moving the motor it would set the command variable to CMD_READY = 0. This way the main program can also sync with the driver and wait until the driver is done before setting the next values.