Shop OBEX P1 Docs P2 Docs Learn Events
Looking for help understanding a PASM led blink object — Parallax Forums

Looking for help understanding a PASM led blink object

turbosupraturbosupra Posts: 1,088
edited 2012-05-07 08:30 in Propeller 1
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.

Comments

  • JonnyMacJonnyMac Posts: 9,195
    edited 2012-05-04 20:43
    That's peculiar code -- let me give you the $0.05 version: You need a mask to control a pin. To create that mask, put #1 into the mask and then shift it left by the pin #. Easy-peazy. To make the pin an output, OR the mask with DIRA. To make the output go high, OR the mask with OUTA. To make the pin go low, ANDN the mask with OUTA.

    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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-04 22:34
    : ) Yes it was your code (see the license) I found in a search, all of the garbage I added to it was just me trying to decipher it and learn from it. I'm going to see if I can find a Nuts and Volts locally at a store to buy and if not I'll subscribe digitally.

    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
  • JonnyMacJonnyMac Posts: 9,195
    edited 2012-05-05 15:01
    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

    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:
    1000_1100
    1001_0011
    ---------
    1001_1111
    

    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:
    1000_1100
    1001_0011
    ---------
    1000_0000
    

    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:
    0111_0011
    1001_0011
    ---------
    0001_0011
    

    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.
    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

    You're a little off: MOV writes the whole register -- it actually copies from source to destination, so it's like
    dira := %11
    

    ...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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-05 22:51
    You are right that was a misstatement, I didn't write that very well and I feel like I understand it more clearly with your explanation, which I appreciate.

    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?
  • msrobotsmsrobots Posts: 3,709
    edited 2012-05-05 23:22
    Hi Turbusupra,

    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
  • JonnyMacJonnyMac Posts: 9,195
    edited 2012-05-06 00:06
    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.

    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.
    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?

    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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-06 14:35
    Thank you both for the replies, I think I'm on the verge of understanding this. All three of these operations perform an instruction operation using a cog register address and an address to a literal 32 bit number (the pinmask in this case)? So when manipulating bits, it isn't manipulating 9 literal source bits and 9 literal destination bits, instead (with the first operation for example) you move the value found at the address for pinmask to the address for dira, so theoretically you could write mov 20A, 20D, if the dira register for that cog was memory address 20A, and the 32 bits for pinmask were stored at memory address 20D?
    mov     dira, pinmask                  
    or      outa, pinmask
    andn    outa, pinmask 
    
    So then when cog0-cog7 has the dira bits read and ORed together, if a single corresponding bit is set to 0 in all cog dira registers, except for one of them is set to 1, when they are ORed together the cog that sets that corresponding dira bit to 1 and controls its function for all 8 cogs, because of the nature of an OR operation. The same with outa and whether a pin is at 0v or 3.3v.

    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?
    That's peculiar code -- let me give you the $0.05 version: You need a mask to control a pin. To create that mask, put #1 into the mask and then shift it left by the pin #. Easy-peazy. To make the pin an output, OR the mask with DIRA. To make the output go high, OR the mask with OUTA. To make the pin go low, ANDN the mask with OUTA.
  • msrobotsmsrobots Posts: 3,709
    edited 2012-05-06 23:29
    exactly, you got it.

    isn't it a nice assembler-language? I really like the prop.

    enjoy!

    Mike
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-07 08:30
    I have no assembly language experience to compare to actually, I just started learning PASM 2 months ago, but I do like it.

    Thank you both for helping me through this! I felt like I was your avatar for a little while there ; )
Sign In or Register to comment.