Looking for help understanding a PASM led blink object
turbosupra
Posts: 1,088
I've been trying to figure out how this object flashes the LED on and off and although it works, I'm just not sure how it is doing it.
I believe it is setting a register value for a pin, and IIRC each cog has it's own registers for each pin, which are ANDed together so that if the direction or output value is 0 in one cog, it's 0 in all cogs?
I would think the ANDN sets the register to output low, and the OR sets the register to output high.
So the source is always configured to output high/1, and ANDN sets the destination to !source/!1 because the logic is if source=1 then the destination=0. Then waits 500mS.
Then the OR says if source or destination is output high/1, and the source is always 1, then it sets the destination from 0 to 1 because the logic is if source=1 or destination=1, then the destination=1. Then it waits 500mS. Is the pin mask is called a pin mask because it is a proverbial overlay on the cogs pin registers to set individual pins to outputs and to high or low?
Am I understanding this correctly? If so, how do I display the changing destination values to the pst, to watch it alternate? The code is set to toggle pin 17 on a parallax demo board.
My goal in understanding this object is to be able to control pins through PASM, with the speed PASM offers, I would like to understand this at a low level.
The code is attached as an archive, thanks for reading.
I believe it is setting a register value for a pin, and IIRC each cog has it's own registers for each pin, which are ANDed together so that if the direction or output value is 0 in one cog, it's 0 in all cogs?
I would think the ANDN sets the register to output low, and the OR sets the register to output high.
So the source is always configured to output high/1, and ANDN sets the destination to !source/!1 because the logic is if source=1 then the destination=0. Then waits 500mS.
Then the OR says if source or destination is output high/1, and the source is always 1, then it sets the destination from 0 to 1 because the logic is if source=1 or destination=1, then the destination=1. Then it waits 500mS. Is the pin mask is called a pin mask because it is a proverbial overlay on the cogs pin registers to set individual pins to outputs and to high or low?
Am I understanding this correctly? If so, how do I display the changing destination values to the pst, to watch it alternate? The code is set to toggle pin 17 on a parallax demo board.
My goal in understanding this object is to be able to control pins through PASM, with the speed PASM offers, I would like to understand this at a low level.
The code is attached as an archive, thanks for reading.
Comments
If you pick up the May Nuts & Volts my column reviews connecting to PASM -- one of the objects (simple, single-pin blinker) I use is attached.
Thank you for the explanation that makes sense, the OR 'copies' the registers source to the destination, the ANDN inverts the source and then copies it to the destination. I understand how to use it now, and I think I understand why it works as well:
I guess DIRA and OUTA (and INA) are special registers in that each bit represents a pin or a pin state, one for each pin?
MOVing the mask to dira is like the spin version of dira[pin#] := 1, with the register dira having the bit that represents that pin number equaling 1 and the rest equaling 0
ORing the mask with outa is like the spin version of outa[pin#] := 1
ANDNing the mask with outa is like the spin version of outa[pin#] := 0
Actually, I don't think you understand -- unless you were attempting to simplify your explanation of what you think is happening (but, then, you've made an eroneous statement that could confuse a newcomer).
Let's back up a bit. What we're dealing with is boolean logic. The OR operator says that if one bit or the other is 1, then the result will be one. In the Propeller the source and destination fields are OR'd together (bit by bit) with the result being moved to the destination register (unless the NR <no result> conditional is used). Here's a easy example:
If you look, column by column, you'll see the "if one bit or the other..." rule in action. So to correct a mistatement, OR does not copy the source to the destination, it ORs the source onto the destination. (The MOV instruction does copy)
Now for AND. If one bit and the other are 1, then the result will be 1. Here it is in action:
Notice that only in the bit8 position to both values have a 1, hence the final output only has a 1 in that position.
Now for ANDN -- this is special; it ANDs the destination register with the compliment (bits inverted) value of the source register. Using the example values from before and assuming the source is the top, internally this is what happens:
This may take a little time to get used to because ANDN is not a common instruction (unless you started with the BASIC Stamp 1 like I did; it exists there, too). As you can see, the bits in the source (top) register are inverted (internally, the source field is not modified) and then AND'd with the destination bits. An easy way to think of it is that any bit with a 1 in the source will result in a 0 in the destination when using ANDN.
You're a little off: MOV writes the whole register -- it actually copies from source to destination, so it's like
...which would set P0 and P1 to output mode, the others would be set to input mode. Note there is no pin identifier in this line; when that happens a mask and OR or ANDN is used.
One thing I'm having a hard time wrapping my head around, if you are using OR/ANDN with the outa register, why do you need to use the 9 bits of the source with the 9 bits of the destination from the OR/ANDN instructions. Since there are only 2 choices for outa (high or low), I'm not sure why you would need the 512 combinations that the 9 bits of either instructions source/destination give you. Because of this, I believe I am missing something there because the propeller manual references source and destination with the OR/ANDN instruction, but it also has the special purpose register for outa defined as "OUTA 4 Read/Write Output States for P31 - P0" which would mean 1 bit represents 1 pin. I'm confused as to how the source and destination bits come into play when the outa special purpose register is a 1 to 1 ratio for bits to pins. Is this a special situation where it is ORing or ANDNing all 32 bits?
Also, if mov dira, pinmask writes the entire register for that cog, (special purpose register 6) can doing that interfere with any of the other cogs special purpose register 6's?
You are allmost there... each cog has its own register ... one bit for each pin.
you can use dira,outa or ina - or use the corresponding (cog-) memory-adress ... does not matter, is the same pasm-bytecode
you manipulate the register of one cog. this cog "see"s its own outa and dira but all cogs see the same ina.
now to the real pins:
if 2 (or mor) cogs are setting the same pin as output the pin will be low if ALL cogs having this pin defined as output set this pin LOW.
it will be high if ONE of the cogs having the pin defined as output sets it to high.
so the cog-register of all cogs are ORed together to set the state of the real pin
if the pin is defined as input it will show the actual state but not influence it...
enjoy!
Mike
ahh and yes - MOVdira,#whatever WILL change ALL 32 pins to avvoid this use OR and ANDN with bitmask
What you're missing is that there are no instructions designed to work on a single bit (like SETB and CLRB in the SX); all bit operations are accomplished using a mask that is 32-bits wide (to match dira, ina, and outa) and could have any number of bits set. For making a pin high or low we just set the appropriate bit in the mask, but other elements of program may in fact need to use multi-bit masks; the instructions are the same. It would help to let go of your focus on pin control and just think about manipulating bits; those bits that are connected to the IO structure of the chip will affect the IO pins. In the cog we have 512 longs which can be addressed by the 9-bit source and destination fields.
As Mike pointed out each cog has its own set of IO registers. The output bits are OR'd together before going to the pin. What this means, then, is that if any cog makes a pin high then that pin will be high, no matter what the other cogs are doing. This can be useful for active-low control. I have written a SONY IR transmitter object that modulates a pin using a counter and controls the modulation pin with another cog; by setting the modulation pin high (which connects to the cathode of the IR LED) the IR signal is stopped; when that pin goes low the modulation is allowed to pass through and the IR is active.
I may have said this before, but there is always a danger learning a new programming language when focusing on a single problem; we tend to see the world in terms of _that_ problem instead of the wider place that it is.
So Jon, back to your first post (this is the drawn out $0.05 version :-) ), create the mask with SHL. Then you OR the dira bits with the pinmask bits via address pointers for dira and pinmask, stored inside of the OR operations source and destination fields, and if either corresponding bit in either address contains a 1 (when ORing corresponding bit values), the final corresponding register bit value comes out of the OR operation as being set as a 1 inside of the dira register. To set the outa value for a bit to one, you use the same methodology and OR [outa address], [pinmask address] so any bits that are 1 in the pinmask register end up being 1 in the outa register because of the nature of the OR operation. If outa previously had some bits set to one, that the pinmask has a corresponding bit set to 0, those bits will continue to be set to 1 because of the nature of of the OR operation. To set a pin low from high, the OR operation would not work, so ANDN is used instead which inverts the pinmask bits and then AND's the values in that address with the values stored in the address of the outa register. This does not affect the other pins inadvertently because any pin not meant to be addressed by the original pinmask is ! (NOTed) to a 1, and then ANDed with the outa registers corresponding bits, so if they were already a 1, they stay that way when added to the values inverted to a 1. If my understanding is correct, that's pretty convenient!
Do I have it?
isn't it a nice assembler-language? I really like the prop.
enjoy!
Mike
Thank you both for helping me through this! I felt like I was your avatar for a little while there ; )