It does not have those exact variations on the blinking led, though it does go through the blinker in good detail, and introduces using more than one cog. I will add those. Funny how a thread can trigger the right thing to do. Was wondering where to go with it. Now I know. Anyway, what is there is useful, and complete enough to benefit from.
Hate to plug my own stuff, but it might be useful to you as a kick start. It got written right when I was really thinking on assembly basics. A contributor here, DeSilva, was writing a more advanced and complete document and didn't have that intro that made sense at the time, so we both wrote something.
I read that material when I first got a Prop -- heck, I read everything I could get my hands on -- and I've got it open in another window as I type this.
Some of the statements there conflict with my own understanding of the Prop's instruction set ... but it could be me, of course! For instance, on Page 23 you show "Adding two unsigned 32 bit numbers" and show the result "(with carry set)". My understanding is that without the "WC" effect specified for the "ADD" the carry flag will be unmodified.
In the intervening text, you explicitly refer to the "WC" and "WZ" effects and how they work ... and then in the 64-bit addition example you don't include the "WC" and then try to add the Carry bit to the result (ADDX).
These are nits. I'm certainly not complaining. That document helped me along.
I did read most of that one. I think i got some of the concepts down. one thing that i didn't get though.
On the demo program, the first line initializes the pin 16. But what makes the dira turn to a output? Is that what the toggle command does? Is that like the post- set command ~~?
Dira is a control register long. All 32 bits are associated with the pins, one bit per pin. When that bit is "1", or set, then that pin is an output pin.
The instruction "mov dira, pin" is all about the labels. "dira" equals the control register COG address. "Pin" refers to the long farther down in the program that holds the value to be put into the control register. In the numbered example, that's long number 6, counting from 0, and you can see the Pin label there.
The "<16" part, means to shift left. It's short hand for this: %00000000_00000001_00000000_00000000.
A mov instruction was used so that all the dira control bit states are known. Essentially, all pins are set to input, but the one we plan on toggling. If two pins were to be toggled, there would need to be two bits set in the dira register, and that long #6 in the program would contain a different value.
Instruction #4, does a logical operation with the outa register, using the same value that was used to set the pin for output. A pin can be high or low in this program, and the "xor" instruction will toggle a bit on and off. If a bit is on, and the xor instruction is used, that bit will be set to off. Another xor instruction will reverse that, and there's your toggle right there.
dira sets the state of the pin, whether it's input or output. outa set the output state, high or low. Both registers associate each of the 32 bits in a long, with the 32 I/O pins. In this case, the same value is handy because it can be used to both set the state and toggle that state.
OH, okay. I know how the dira register works in spin. I was just wondering how one sets the dira register in PASM and now i know, sort of. I think i am getting it, but it still seems very different from a higher level language.
Basically, you put a number in the register, and the bits that form the number cause the hardware to do things.
The key thing to understand is how the number gets written to the register! The value written, along with the operator used, impacts the result seen.
If you do a MOV, all the states of all the bits will be exactly as specified in the source portion of the MOV instruction. In other words, MOV impacts all the bits to reflect the 1 and 0 state. MOV is used in the sample program because it's an easy case. Only one pin should be output, with the others all input.
If you do an OR operation, that's different. An OR basically will only flip a bit to an on state, if the source value bit is a one. Where the source value is a zero, the register bit is untouched! Where it's a 1, that particular bit will be set to a 1, or on state. This lets you change, say bits, 1, 15, 23, without impacting the other ones. You set all the bits in the source value to 0, but for those you want to set.
If you do an AND operation, it's different still. And will only result in a 1, if both the source bit and register bit are 1, otherwise it's zero. And could be used as the inverse of OR, in that you might want to set some bits to zero, while leaving the others alone. You set all ones in the source value, but for the bits you want to clear, which would be zero.
In higher level languages, that stuff is abstracted, allowing you to specify things like pin numbers and states. In PASM, there is just the register and values and operations. You combine the register, with the value and operation that suits your needs. A commonly used value is often called a mask, and you think of it like a paint stencil, where the active operation only impacts a portion of the target material. Registers, bits and the operators, MOV, AND, OR... do the same thing.
With the following assembly code, I am setting ctra to NCO mode and to output to pin 22...
mov ctra, CtraNCOp22······· 'Set ctra for NCO single-ended output to Pin 22"
CtraNCOp22·long· %00010000_00000000__00000000_00010110 '%00100 and pin 22
Note: "CtraNCOp22" is my name I have assigned to this. This could be called "Foo" or whatever. And would of course need to be called "Foo" on both lines.
The counters or ctra / ctrb documentation is the *most* difficult part of the Propeller to understand. But basically there is an entire register which can all be set at one time which I have done with my long list of 0's and 1's. Or you can set just portions of that register with "bit manipulation".
I like the 0's and 1's above because I can "see" exactly what is being written/stored/moved to the entire register. I know exactly what every bit in that register is set to.
In spin, you can do the same thing as above with the following which just sets specific areas of the register...
· 'Configure ctra module. · ctra[noparse][[/noparse]30..26] := %00100····· ' Set ctra for "NCO single-ended" · ctra[noparse][[/noparse]5..0] := 22··········· ' Set APIN to P22
One thing which is confusing is how do you set the output? The output is "APIN" and the documentation is not clear on this. So what "APIN" is set to is what pin the output will go to. There are two counters, A and B. Or ctra and ctrb. The output of counter A would be determined by the setting of "APIN". And the output of counter B would be determined by the setting of "BPIN".
EDIT: The above was incorrect, see following posts for correction.
Above in the second line, easy to see it is set to pin 22 because it says 22.
In the line "ctra[noparse][[/noparse]30..26] := %00100", the "30..26" part means just set "bits" of the counter register (1's and 0's)·30 through 26.
And that is what this is doing -> 00100
The 0 to the furthest right is bit 26, furthest left is 30. In the middle is bit 28 and is set to a 1.
This does the same thing as well as also setting the pin number...
00010000_00000000__00000000_00010110
This (00100) is on the left side. Bit 28 is the 1. Count from right to left, 0, 1, 2, 3, 4, etc. and·when you get to 28, there is that 1.
The entire "register" is like a filing cabinet drawer. It holds *all* the settings for the counter in that whole drawer. And the individual "files" within that drawer would be like individual settings for mode or the output pin. You can set just one thing, or the entire works all at once.
The entire "register" is shown in the documentation like this...
CTRA and CTRB Registers
31 30..26 25..23 22..15 14..9 8..6 5..0
- CTRMODE PLLDIV - BPIN - APIN
So that register is 31 bits long. Or might like like this...
Another thing which is confusing is the PLLDIV part. This is where in programming microcontrollers you need to understand the hardware. In NCO mode, the output bypasses the PLL part of the counter entirely.
As to the chart·listing settings...
APIN Output - "PHSx[noparse][[/noparse]31]" means the direct output of PHSx·bit 31!
APIN Output - "PLLx" means it goes through the PLL first.
APIN Output - "PHSx-Carry" means it is the carry or overflow of PHSx (slower or like a bit 32 or a 33rd bit [noparse][[/noparse]32 start counting at 0, 33 start counting at 1]).
One thing which is confusing is how do you set the output? The output is "APIN" and the documentation is not clear on this. So what "APIN" is set to is what pin the output will go to. There are two counters, A and B. Or ctra and ctrb. The output of counter A would be determined by the setting of "APIN". And the output of counter B would be determined by the setting of "BPIN".
Not quite correct I'm afraid.
There are two counters in each cog, CTRA & CTRB. Each counter has two pins it can control. APIN and BPIN. So there are ultimately 4 pins per cog that can be used by the counters.
You can set the APIN of a counter with
CTRA |= (Pin No.)
You set the BPIN with
CTRA |= (Pin No.) << 9
.. where (Pin No.) is between 0 & 31.
If you are using these pins as outputs, you also need to set the corresponding bits in the DIRA register or nothing will happen.
Start at page 95 of the Propeller Manual v1.1 for a reasonable explanation of configuring the counters.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"Are you suggesting coconuts migrate?"
Zap-o said...
I find assembly on the propeller difficult because of the lack of a good book and the way you have to send data over from the hub.
As Holly pointed out -- and I took advantage of this week -- one can use PropBASIC as a tool for quick testing of Assembly segments as the output is native assembly. This saves the trouble of creating an interface and launching a cog.
[noparse][[/noparse] Edit ]· If you don't want to go the PropBASIC route to experiment with PASM, the attached file may help.· I set it up for myself so that I could test small sections of PASM.· The assembly is a command interface where you can set a command value and one or·two parameters (very easy to change).·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
One thing which is confusing is how do you set the output? The output is "APIN" and the documentation is not clear on this. So what "APIN" is set to is what pin the output will go to. There are two counters, A and B. Or ctra and ctrb. The output of counter A would be determined by the setting of "APIN". And the output of counter B would be determined by the setting of "BPIN".
Not quite correct I'm afraid.
There are two counters in each cog, CTRA & CTRB. Each counter has two pins it can control. APIN and BPIN. So there are ultimately 4 pins per cog that can be used by the counters.
You can set the APIN of a counter with
CTRA |= (Pin No.)
You set the BPIN with
CTRA |= (Pin No.) << 9
See I've read all this stuff 3 times and I still don't have it right!
@Potatohead.....I understand how logic gates work in theory and in some in practice. I bought a bunch of old 74 and 4000 series logic gates and during my first years of experimentation, i learned how they work by themselves. My problem with logic gates comes in whenever Micro controllers are involved. I mean i know that OR gates will produce a one if either input is a one, and i know a NOT gate is just a inverter, and i know that AND gates will only output a one if all inputs are a one.....ect. So about assembly. All that the MOV instruction does is just copy two numbers, right? So for the pin variable thing, instead of saying <16, could you just say something like this?
pin long %00000000_00000001_00000000_00000000
When it comes to pin I/O i always like to visualize the whole port by using raw binary....I guess i am weird, but it just seems eaiser to me
@bill190.... Yeah, The CTRA and CRTB register was the hardest to visualize. And you are right, it is way easier to "see" the register with the long binary list.
@Jonnymac.... I have heard so much about this "PropBASIC". Do you have a link for it?
@BradC.... Good catch. Having two pins for the CTR registers makes a lot more flexiable.
Yes, it's easier for me as well. All mov does is copy the number. The bits in the number, change the states of the gates, and stuff happens. The key thing to understand is that mov will change all the states of all the bits at once.
That's the core of assembly language. All that is really happening at any one time is moving numbers, operating on them (and or, etc..), and adding them together.
So there is understanding of what the instruction literally does. What the impact of that is, depends on how the hardware is built, both the CPU and the stuff connected to it.
I will often evaluate short cut expressions, then plug the binary into the program to see if I got it. If things run the same, I probably did. If not, then I know I've got some stuff to do and learn.
If you understand the gates, then all you really need to do is understand why you use the operators instead of a mov instruction.
Generally, mov impacts the entire destination, no questions asked. Another way to think of this is mov will impact all 32 bits.
There are times when you only want to impact some of the bits, or maybe just one of them. That's what the operators are for. In this case, let's say that some of the pins are connected to other things, like maybe a few leds you want to blink at different times. For simplicity here, and because many people have a demo board, let's say pins 0, 2, 3 have leds on them. So that's three.
Breaking down a few useful instructions might be really helpful:
We need them to all be outputs, right?
mov dira, #%1101
That's a literal, meaning the value %1101 is in the instruction itself. The biggest literal is $1ff, because the rest of the bits detail what the instruction does. What gets written to dira, is 00000000_00000000_00000000_00001101
The impact of that is all pins are set to input, regardless of their prior state, with the pins we want to toggle being set to output. All 32 bits are changed, no matter what.
Let's say we start with all the leds on!
mov outa, #%1101
Again, same process. All pins are pulled low, but for the ones we picked.
Now there is a state we need to be aware of going forward. If we want to turn pin 0 off, we know there is a 0 that needs to get written to outa, bit 0. But, we also want to leave the other pins alone, and do so conditionally.
If all we had was the mov instruction, we would need lots of jmp instructions and stored binary numbers to handle all the combinations! That's impossible to do in a practical way.
Enter the operators!!
To turn pin 0 off, we need the AND instruction. The result of an and is only a 1, if both the source and destination bits are 1. Essentially then, and allows us to turn a single bit off, without impacting the other bits!
and outa, #%1110
Since there is a zero in the bit 0 position, we know that will force the outa bit 0 to be set to the low, or 0 state. The other bits will be either low or high, and be untouched, because of how and works.
To turn pin 0 on, without touching the other ones, we use the or instruction.
or outa, #%0001
It's the opposite of and! Or will set the destination bit to a 1, if either the source or destination bit is a 1.
These three instructions are the core of assembly language, where actually controlling the state of things is concerned. Mov sets the state of all the bits in the destination, erasing the state of them that was there before.
And can turn a single bit, of the 32 we are working with off, without changing the state of the other bits, using a mask. Put ones everywhere, but for the bits to be cleared, and it's a done deal.
Or can turn a single bit on, of the 32 being worked with, using a mask also. Put zeroes everywhere, but for the bits to be set, or turned on, and it's done.
Does that help?
Edit:
To turn the led connected to pin 2 on, without impacting the other leds, connected to the other pins, you would do
OH my gosh, Thank you potatohead for the in-depth teaching. I think i finally get it, maybe.
your first command simply declared some pins as outputs. That is what the MOV instruction does. It copies the %1011 directly to the DIRA register
The second instruction declares a few outputs as a 1 or high. Once again using the MOV instruction. This is also what OUTA will remain as, seeing as the next instructions are not MOV's, but rather bit wise operators
The rest of the commands simply take the OUTA register and the new data and preform logic on them. How does the OR and AND operators not effect the whole register?
And the source is the binary e.g %1110 and the destination is the outa register?
If you still must manipulate the whole OUTA register, Than why not just do a MOV every time?
Well, the other bits in outa won't be impacted by the AND and OR instruction, because of how the gates work. What if you need to blink the three LEDs on and off at different times?
If all you use is MOV, then you've got to either calculate or include all the possible values in your program, select the right one, then do the MOV to get it done, right?
For three LEDs, that's the following table of values:
%1101 - All pins on
%1100 - Pins 2 and 3 on, pin 0 off
%1001 - Pin 0 on, pin 2 off, pin three on
%1000 - Pin 0 off, pin 2 off, pin three on
%0101 - Pin 0 on, pin 2 on, pin three off
%0100 - Pin 0 off, pin 2 on, pin three off
%0001 - Pin 0 on, others off
%0000 - All off
What a PITA! A lot of instructions are gonna have to happen to get that all sorted out, and the more instructions you use, the slower things go, the more bugs there are, and the less things you can have the chip do in it's memory space. MOV forces you do deal with the entire problem at one time, because it changes the entire register at one time. The result of a MOV will be according to the table above. For starting out, that's great. But once the program starts doing stuff, it's not practical.
In order to pick the right value for MOV, it is necessary to examine the register, then somehow select the right value from the table above to get the desired result. Frankly, I don't even know how to code this!
When you use OR and AND, it's not necessary to read the outa register at all! All you to is decide which LED, or LED's you want to light up, and perform the operation. Let's look at a similar table for AND first:
%1111 - All pins untouched (useless)
%1110 - Pins 2 and 3 untouched, pin 0 off
%1011 - Pin 2 off, pins 0 and 3 untouched
%1010 - Pin 0 and 2 off, pin 3 untouched
%0111 - Pin 0 and pin 2 untouched, pin 3 off
%0110 - Pin 0 off, pin 2 untouched, pin 3 off
%0011 - Pin 0 untouched, pins 2 and 3 set off
%0010 - All off, for sure.
Notice bit 1. It's always a 1. Why? Because we don't want to mess with bit one at all. There is no LED connected, and maybe it's doing something else important. By putting a 1 there, we've MASKED off that bit, so that it won't be changed by the AND operation. All the possible conditions you might need are there. You can impact any of the bits in any way, without disturbing the ones that are not part of the program purpose at that particular time.
Now, OR
%1101 - All pins on
%1100 - Pins 2 and 3 on, pin 0 untouched
%1001 - Pin 2 untouched, pins 0 and 3 on
%1000 - Pin 0 and 2 untouched, pin 3 on
%0101 - Pin 0 and pin 2 on, pin 3 untouched
%0100 - Pin 0 off, pin 2 on, pin 3 untouched
%0001 - Pin 0 on, pins 2 and 3 untouched
%0000 - All untouched. (useless)
When you program your purpose in PASM, there will be loops and states that change, depending on computations, counters, inputs, etc... At some point your program will make a decision to do something other than what it was doing prior to that decision. The operators allow you to act on those pins that matter, according to the result of the decision, leaving the ones that don't matter, out of the equation, until their time comes.
This happens all the time in graphics, which I find is one of the easiest ways to get the bit operators, and how they are different from MOV.
Look at your computer screen. There are pixels all over the place. And there is your mouse pointer. When you move the mouse pointer around, assembly language instructions are operating on the bits of the screen memory. If we want to see a nice, clean mouse pointer, and have it move at a single pixel position, it's necessary to only write some of the bits and not others, because the bits not written have some meaning outside the mouse pointer part of the program.
The bit operators allow the programmer to only draw the mouse on top of what another programmer, or part of the program has already drawn, like a window with text in it. It's the same thing.
You, the programmer, will very rapidly reach a point where you want to impact one LED, without having to worry about what has been done with the other ones.
Bit operators are good for other things too.
The system counter runs very fast, one tick per clock cycle. Maybe it's a good idea to just take the lower 8 bits of the counter as some kind of simple pseudo random number. The bit operators get us this, very quickly.
Capture the counter value
mov lower_8_bits, cnt
mask off all but the lower 8 bits
and lower_8_bits, #%11111111
Because of how AND works, we know the upper 24 bits will be zero, leaving whatever was in the lower 8 bits at the time to work with elsewhere in the program.
Okay, i think i am getting it. So The MOV instruction is sort of like writing a whole port, but the bit wise operators are kind of like writing a single pin. So If you use the OR and AND commands, other pins will not be affected at all? And i know how XOR gates work in real life, but how does that toggle the pin? And you said that the MOV instruction is one of the only commands used? Then how would one have any conditional looping?
Yeah, that's it exactly. You choose which pins, or pin is written with the mask value. If you change the mask, the same code will impact different pins.
The toggle is just how XOR works. The sample program is just a loop that repeatedly XORes the destination port pin, using the same mask value that was used to set it to output in dira. The very first XOR, turns the output pin on, with subsequent ones turning it off, or on, depending on what state it's in when the XOR happens.
It's really helpful to step through that sample program, using just pencil and paper, tracking the state of things. Just mentally run each instruction, and write the contents of the registers. Do this chart style, with a row of addresses and registers across the top, filling everything in, one line at a time for each loop through. After a few, you will get it.
The truth table for XOR is:
source = 0, destination = 0, then destination = 0
source = 0, destination = 1, then destination = 1
source = 1, destination = 1, then destination = 1
source = 1, destination = 1, then destination = 0
With XOR, the state of the destination bits will be toggled from off to on, or on to off, when the source bit is a 1. When the source bit is a 0, the state of the destination bits is untouched.
That's your toggle in the sample program.
I think we ended up in the weeds on conditional looping. If you understand the operators, and how they operate different from MOV, then you can move on to other things, like tests and loops.
Once you understand how the operators allow us to isolate individual bits, or pins with a mask, then it's possible to use those operators for lots of things.
One is to do testing. Let's say pins 0-7 are all input pins, each connected to something. There are 256 on / off state combinations possible. (0-255)
If you want to see whether or not any of the pins, 1, 3, and 4 are on, you need a mask to start with: %00011010
A MOV instruction could capture the ina register, copying it to a working long in the COG for some testing. MOV captures all 32 bits, just as it writes all 32 bits. Let's say that long is just called _input.
To test the pins, you could do:
and _input, #%00011010 NR, WZ
This instruction form is one of the more powerful things about the Propeller. The "NR" effect, means we want the Prop to perform the AND operation, but we don't want the result written to the destination register, because some more tests need to be done. The WZ effect, means we want to set the state of the Z (zero) flag, based on the result of the AND operation.
After this instruction, the Z flag will be 0, if any of the pins were on, and 1, if they were all off. A JMP instruction, with the condition bits set, would change program flow, based on the input pin states.
if_nz JMP #address
If you decide to write the result, all the bits would be cleared in that _input long, but where there was a 1 in both the source or destination. From there, using the CMP instruction, could tell you whether or not the value of the mask is equal to the value of the product of the ANDing the _input register too. That's a simple case for testing for the all on state.
That's the beginnings of conditional looping. Collect the data, operate on it to isolate the bits of interest, compare to known mask values, JMP based on the result of the comparison (Z and C flag).
Yeah, your right about taking it slow. Sorry, i tend to get ahead of myself. I will skip right over level 1 and go right to level 30, only to realize i have no idea what i am doing.
Actually i just moved, so it might take a while to set me lab back up. I am not very far yet, but i hope to be experimenting tommorrow at the latest. Thanks for staying on board.
Ok then. I'm seeing just the kind of thing needed to expand my absolute beginner document. That one takes it really easy, and gets a lot of core basics done, but I wasn't sure where to take it. It's a good thing all around.
Comments
It does not have those exact variations on the blinking led, though it does go through the blinker in good detail, and introduces using more than one cog. I will add those. Funny how a thread can trigger the right thing to do. Was wondering where to go with it. Now I know. Anyway, what is there is useful, and complete enough to benefit from.
Hate to plug my own stuff, but it might be useful to you as a kick start. It got written right when I was really thinking on assembly basics. A contributor here, DeSilva, was writing a more advanced and complete document and didn't have that intro that made sense at the time, so we both wrote something.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Some of the statements there conflict with my own understanding of the Prop's instruction set ... but it could be me, of course! For instance, on Page 23 you show "Adding two unsigned 32 bit numbers" and show the result "(with carry set)". My understanding is that without the "WC" effect specified for the "ADD" the carry flag will be unmodified.
In the intervening text, you explicitly refer to the "WC" and "WZ" effects and how they work ... and then in the 64-bit addition example you don't include the "WC" and then try to add the Carry bit to the result (ADDX).
These are nits. I'm certainly not complaining. That document helped me along.
Tom.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Try this:
http://forums.parallax.com/attachment.php?attachmentid=58857
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
On the demo program, the first line initializes the pin 16. But what makes the dira turn to a output? Is that what the toggle command does? Is that like the post- set command ~~?
The instruction "mov dira, pin" is all about the labels. "dira" equals the control register COG address. "Pin" refers to the long farther down in the program that holds the value to be put into the control register. In the numbered example, that's long number 6, counting from 0, and you can see the Pin label there.
The "<16" part, means to shift left. It's short hand for this: %00000000_00000001_00000000_00000000.
A mov instruction was used so that all the dira control bit states are known. Essentially, all pins are set to input, but the one we plan on toggling. If two pins were to be toggled, there would need to be two bits set in the dira register, and that long #6 in the program would contain a different value.
Instruction #4, does a logical operation with the outa register, using the same value that was used to set the pin for output. A pin can be high or low in this program, and the "xor" instruction will toggle a bit on and off. If a bit is on, and the xor instruction is used, that bit will be set to off. Another xor instruction will reverse that, and there's your toggle right there.
dira sets the state of the pin, whether it's input or output. outa set the output state, high or low. Both registers associate each of the 32 bits in a long, with the 32 I/O pins. In this case, the same value is handy because it can be used to both set the state and toggle that state.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
The key thing to understand is how the number gets written to the register! The value written, along with the operator used, impacts the result seen.
If you do a MOV, all the states of all the bits will be exactly as specified in the source portion of the MOV instruction. In other words, MOV impacts all the bits to reflect the 1 and 0 state. MOV is used in the sample program because it's an easy case. Only one pin should be output, with the others all input.
If you do an OR operation, that's different. An OR basically will only flip a bit to an on state, if the source value bit is a one. Where the source value is a zero, the register bit is untouched! Where it's a 1, that particular bit will be set to a 1, or on state. This lets you change, say bits, 1, 15, 23, without impacting the other ones. You set all the bits in the source value to 0, but for those you want to set.
If you do an AND operation, it's different still. And will only result in a 1, if both the source bit and register bit are 1, otherwise it's zero. And could be used as the inverse of OR, in that you might want to set some bits to zero, while leaving the others alone. You set all ones in the source value, but for the bits you want to clear, which would be zero.
In higher level languages, that stuff is abstracted, allowing you to specify things like pin numbers and states. In PASM, there is just the register and values and operations. You combine the register, with the value and operation that suits your needs. A commonly used value is often called a mask, and you think of it like a paint stencil, where the active operation only impacts a portion of the target material. Registers, bits and the operators, MOV, AND, OR... do the same thing.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
mov ctra, CtraNCOp22······· 'Set ctra for NCO single-ended output to Pin 22"
CtraNCOp22·long· %00010000_00000000__00000000_00010110 '%00100 and pin 22
Note: "CtraNCOp22" is my name I have assigned to this. This could be called "Foo" or whatever. And would of course need to be called "Foo" on both lines.
The counters or ctra / ctrb documentation is the *most* difficult part of the Propeller to understand. But basically there is an entire register which can all be set at one time which I have done with my long list of 0's and 1's. Or you can set just portions of that register with "bit manipulation".
I like the 0's and 1's above because I can "see" exactly what is being written/stored/moved to the entire register. I know exactly what every bit in that register is set to.
In spin, you can do the same thing as above with the following which just sets specific areas of the register...
· 'Configure ctra module.
· ctra[noparse][[/noparse]30..26] := %00100····· ' Set ctra for "NCO single-ended"
· ctra[noparse][[/noparse]5..0] := 22··········· ' Set APIN to P22
One thing which is confusing is how do you set the output? The output is "APIN" and the documentation is not clear on this. So what "APIN" is set to is what pin the output will go to. There are two counters, A and B. Or ctra and ctrb. The output of counter A would be determined by the setting of "APIN". And the output of counter B would be determined by the setting of "BPIN".
EDIT: The above was incorrect, see following posts for correction.
Above in the second line, easy to see it is set to pin 22 because it says 22.
In the line "ctra[noparse][[/noparse]30..26] := %00100", the "30..26" part means just set "bits" of the counter register (1's and 0's)·30 through 26.
And that is what this is doing -> 00100
The 0 to the furthest right is bit 26, furthest left is 30. In the middle is bit 28 and is set to a 1.
This does the same thing as well as also setting the pin number...
00010000_00000000__00000000_00010110
This (00100) is on the left side. Bit 28 is the 1. Count from right to left, 0, 1, 2, 3, 4, etc. and·when you get to 28, there is that 1.
The entire "register" is like a filing cabinet drawer. It holds *all* the settings for the counter in that whole drawer. And the individual "files" within that drawer would be like individual settings for mode or the output pin. You can set just one thing, or the entire works all at once.
The entire "register" is shown in the documentation like this...
CTRA and CTRB Registers
31 30..26 25..23 22..15 14..9 8..6 5..0
- CTRMODE PLLDIV - BPIN - APIN
So that register is 31 bits long. Or might like like this...
00010000_00000000__00000000_00010110 (Look familiar?)
There is an additional document on just the Propeller counters. That is called "AN001 - Propeller Counters v1.0" and is here...
http://forums.parallax.com/attachment.php?attachmentid=59613
Another thing which is confusing is the PLLDIV part. This is where in programming microcontrollers you need to understand the hardware. In NCO mode, the output bypasses the PLL part of the counter entirely.
As to the chart·listing settings...
APIN Output - "PHSx[noparse][[/noparse]31]" means the direct output of PHSx·bit 31!
APIN Output - "PLLx" means it goes through the PLL first.
APIN Output - "PHSx-Carry" means it is the carry or overflow of PHSx (slower or like a bit 32 or a 33rd bit [noparse][[/noparse]32 start counting at 0, 33 start counting at 1]).
APIN Output - "0" means no output.
Post Edited (bill190) : 5/22/2010 7:55:11 PM GMT
Not quite correct I'm afraid.
There are two counters in each cog, CTRA & CTRB. Each counter has two pins it can control. APIN and BPIN. So there are ultimately 4 pins per cog that can be used by the counters.
You can set the APIN of a counter with
CTRA |= (Pin No.)
You set the BPIN with
CTRA |= (Pin No.) << 9
.. where (Pin No.) is between 0 & 31.
If you are using these pins as outputs, you also need to set the corresponding bits in the DIRA register or nothing will happen.
Start at page 95 of the Propeller Manual v1.1 for a reasonable explanation of configuring the counters.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"Are you suggesting coconuts migrate?"
As Holly pointed out -- and I took advantage of this week -- one can use PropBASIC as a tool for quick testing of Assembly segments as the output is native assembly. This saves the trouble of creating an interface and launching a cog.
[noparse][[/noparse] Edit ]· If you don't want to go the PropBASIC route to experiment with PASM, the attached file may help.· I set it up for myself so that I could test small sections of PASM.· The assembly is a command interface where you can set a command value and one or·two parameters (very easy to change).·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
Post Edited (JonnyMac) : 5/22/2010 5:43:12 PM GMT
See I've read all this stuff 3 times and I still don't have it right!
Thanks!
·
pin long %00000000_00000001_00000000_00000000
When it comes to pin I/O i always like to visualize the whole port by using raw binary....I guess i am weird, but it just seems eaiser to me
@bill190.... Yeah, The CTRA and CRTB register was the hardest to visualize. And you are right, it is way easier to "see" the register with the long binary list.
@Jonnymac.... I have heard so much about this "PropBASIC". Do you have a link for it?
@BradC.... Good catch. Having two pins for the CTR registers makes a lot more flexiable.
And to all, thank you for the help.
PropBASIC = http://forums.parallax.com/showthread.php?p=755835
Note that PropBASIC only runs in BST.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
That's the core of assembly language. All that is really happening at any one time is moving numbers, operating on them (and or, etc..), and adding them together.
So there is understanding of what the instruction literally does. What the impact of that is, depends on how the hardware is built, both the CPU and the stuff connected to it.
I will often evaluate short cut expressions, then plug the binary into the program to see if I got it. If things run the same, I probably did. If not, then I know I've got some stuff to do and learn.
If you understand the gates, then all you really need to do is understand why you use the operators instead of a mov instruction.
Generally, mov impacts the entire destination, no questions asked. Another way to think of this is mov will impact all 32 bits.
There are times when you only want to impact some of the bits, or maybe just one of them. That's what the operators are for. In this case, let's say that some of the pins are connected to other things, like maybe a few leds you want to blink at different times. For simplicity here, and because many people have a demo board, let's say pins 0, 2, 3 have leds on them. So that's three.
Breaking down a few useful instructions might be really helpful:
We need them to all be outputs, right?
mov dira, #%1101
That's a literal, meaning the value %1101 is in the instruction itself. The biggest literal is $1ff, because the rest of the bits detail what the instruction does. What gets written to dira, is 00000000_00000000_00000000_00001101
The impact of that is all pins are set to input, regardless of their prior state, with the pins we want to toggle being set to output. All 32 bits are changed, no matter what.
Let's say we start with all the leds on!
mov outa, #%1101
Again, same process. All pins are pulled low, but for the ones we picked.
Now there is a state we need to be aware of going forward. If we want to turn pin 0 off, we know there is a 0 that needs to get written to outa, bit 0. But, we also want to leave the other pins alone, and do so conditionally.
If all we had was the mov instruction, we would need lots of jmp instructions and stored binary numbers to handle all the combinations! That's impossible to do in a practical way.
Enter the operators!!
To turn pin 0 off, we need the AND instruction. The result of an and is only a 1, if both the source and destination bits are 1. Essentially then, and allows us to turn a single bit off, without impacting the other bits!
and outa, #%1110
Since there is a zero in the bit 0 position, we know that will force the outa bit 0 to be set to the low, or 0 state. The other bits will be either low or high, and be untouched, because of how and works.
To turn pin 0 on, without touching the other ones, we use the or instruction.
or outa, #%0001
It's the opposite of and! Or will set the destination bit to a 1, if either the source or destination bit is a 1.
These three instructions are the core of assembly language, where actually controlling the state of things is concerned. Mov sets the state of all the bits in the destination, erasing the state of them that was there before.
And can turn a single bit, of the 32 we are working with off, without changing the state of the other bits, using a mask. Put ones everywhere, but for the bits to be cleared, and it's a done deal.
Or can turn a single bit on, of the 32 being worked with, using a mask also. Put zeroes everywhere, but for the bits to be set, or turned on, and it's done.
Does that help?
Edit:
To turn the led connected to pin 2 on, without impacting the other leds, connected to the other pins, you would do
or dira, #%0100
off would be and dira, #%1011
etc...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 5/22/2010 5:54:08 PM GMT
your first command simply declared some pins as outputs. That is what the MOV instruction does. It copies the %1011 directly to the DIRA register
The second instruction declares a few outputs as a 1 or high. Once again using the MOV instruction. This is also what OUTA will remain as, seeing as the next instructions are not MOV's, but rather bit wise operators
The rest of the commands simply take the OUTA register and the new data and preform logic on them. How does the OR and AND operators not effect the whole register?
And the source is the binary e.g %1110 and the destination is the outa register?
If you still must manipulate the whole OUTA register, Than why not just do a MOV every time?
Thanks again for the patience.
If all you use is MOV, then you've got to either calculate or include all the possible values in your program, select the right one, then do the MOV to get it done, right?
For three LEDs, that's the following table of values:
%1101 - All pins on
%1100 - Pins 2 and 3 on, pin 0 off
%1001 - Pin 0 on, pin 2 off, pin three on
%1000 - Pin 0 off, pin 2 off, pin three on
%0101 - Pin 0 on, pin 2 on, pin three off
%0100 - Pin 0 off, pin 2 on, pin three off
%0001 - Pin 0 on, others off
%0000 - All off
What a PITA! A lot of instructions are gonna have to happen to get that all sorted out, and the more instructions you use, the slower things go, the more bugs there are, and the less things you can have the chip do in it's memory space. MOV forces you do deal with the entire problem at one time, because it changes the entire register at one time. The result of a MOV will be according to the table above. For starting out, that's great. But once the program starts doing stuff, it's not practical.
In order to pick the right value for MOV, it is necessary to examine the register, then somehow select the right value from the table above to get the desired result. Frankly, I don't even know how to code this!
When you use OR and AND, it's not necessary to read the outa register at all! All you to is decide which LED, or LED's you want to light up, and perform the operation. Let's look at a similar table for AND first:
%1111 - All pins untouched (useless)
%1110 - Pins 2 and 3 untouched, pin 0 off
%1011 - Pin 2 off, pins 0 and 3 untouched
%1010 - Pin 0 and 2 off, pin 3 untouched
%0111 - Pin 0 and pin 2 untouched, pin 3 off
%0110 - Pin 0 off, pin 2 untouched, pin 3 off
%0011 - Pin 0 untouched, pins 2 and 3 set off
%0010 - All off, for sure.
Notice bit 1. It's always a 1. Why? Because we don't want to mess with bit one at all. There is no LED connected, and maybe it's doing something else important. By putting a 1 there, we've MASKED off that bit, so that it won't be changed by the AND operation. All the possible conditions you might need are there. You can impact any of the bits in any way, without disturbing the ones that are not part of the program purpose at that particular time.
Now, OR
%1101 - All pins on
%1100 - Pins 2 and 3 on, pin 0 untouched
%1001 - Pin 2 untouched, pins 0 and 3 on
%1000 - Pin 0 and 2 untouched, pin 3 on
%0101 - Pin 0 and pin 2 on, pin 3 untouched
%0100 - Pin 0 off, pin 2 on, pin 3 untouched
%0001 - Pin 0 on, pins 2 and 3 untouched
%0000 - All untouched. (useless)
When you program your purpose in PASM, there will be loops and states that change, depending on computations, counters, inputs, etc... At some point your program will make a decision to do something other than what it was doing prior to that decision. The operators allow you to act on those pins that matter, according to the result of the decision, leaving the ones that don't matter, out of the equation, until their time comes.
This happens all the time in graphics, which I find is one of the easiest ways to get the bit operators, and how they are different from MOV.
Look at your computer screen. There are pixels all over the place. And there is your mouse pointer. When you move the mouse pointer around, assembly language instructions are operating on the bits of the screen memory. If we want to see a nice, clean mouse pointer, and have it move at a single pixel position, it's necessary to only write some of the bits and not others, because the bits not written have some meaning outside the mouse pointer part of the program.
The bit operators allow the programmer to only draw the mouse on top of what another programmer, or part of the program has already drawn, like a window with text in it. It's the same thing.
You, the programmer, will very rapidly reach a point where you want to impact one LED, without having to worry about what has been done with the other ones.
Bit operators are good for other things too.
The system counter runs very fast, one tick per clock cycle. Maybe it's a good idea to just take the lower 8 bits of the counter as some kind of simple pseudo random number. The bit operators get us this, very quickly.
Capture the counter value
mov lower_8_bits, cnt
mask off all but the lower 8 bits
and lower_8_bits, #%11111111
Because of how AND works, we know the upper 24 bits will be zero, leaving whatever was in the lower 8 bits at the time to work with elsewhere in the program.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
The toggle is just how XOR works. The sample program is just a loop that repeatedly XORes the destination port pin, using the same mask value that was used to set it to output in dira. The very first XOR, turns the output pin on, with subsequent ones turning it off, or on, depending on what state it's in when the XOR happens.
It's really helpful to step through that sample program, using just pencil and paper, tracking the state of things. Just mentally run each instruction, and write the contents of the registers. Do this chart style, with a row of addresses and registers across the top, filling everything in, one line at a time for each loop through. After a few, you will get it.
The truth table for XOR is:
source = 0, destination = 0, then destination = 0
source = 0, destination = 1, then destination = 1
source = 1, destination = 1, then destination = 1
source = 1, destination = 1, then destination = 0
With XOR, the state of the destination bits will be toggled from off to on, or on to off, when the source bit is a 1. When the source bit is a 0, the state of the destination bits is untouched.
That's your toggle in the sample program.
I think we ended up in the weeds on conditional looping. If you understand the operators, and how they operate different from MOV, then you can move on to other things, like tests and loops.
Once you understand how the operators allow us to isolate individual bits, or pins with a mask, then it's possible to use those operators for lots of things.
One is to do testing. Let's say pins 0-7 are all input pins, each connected to something. There are 256 on / off state combinations possible. (0-255)
If you want to see whether or not any of the pins, 1, 3, and 4 are on, you need a mask to start with: %00011010
A MOV instruction could capture the ina register, copying it to a working long in the COG for some testing. MOV captures all 32 bits, just as it writes all 32 bits. Let's say that long is just called _input.
To test the pins, you could do:
and _input, #%00011010 NR, WZ
This instruction form is one of the more powerful things about the Propeller. The "NR" effect, means we want the Prop to perform the AND operation, but we don't want the result written to the destination register, because some more tests need to be done. The WZ effect, means we want to set the state of the Z (zero) flag, based on the result of the AND operation.
After this instruction, the Z flag will be 0, if any of the pins were on, and 1, if they were all off. A JMP instruction, with the condition bits set, would change program flow, based on the input pin states.
if_nz JMP #address
If you decide to write the result, all the bits would be cleared in that _input long, but where there was a 1 in both the source or destination. From there, using the CMP instruction, could tell you whether or not the value of the mask is equal to the value of the product of the ANDing the _input register too. That's a simple case for testing for the all on state.
That's the beginnings of conditional looping. Collect the data, operate on it to isolate the bits of interest, compare to known mask values, JMP based on the result of the comparison (Z and C flag).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 5/23/2010 5:45:16 PM GMT
and _input, #%00011010 NR, WZ
Was is the _input? Is that a variable?
So conditional looping is not as hard as i thought. the flags determine if the program should jump or not?
Every time i think i got it seems like i lose that reassurance. I really do want to learn this, no matter how many times i mess up. Please, continue.
_input is just a long in the COG, with a label. I like to use underscores as a purpose marker, that's all.
Yep, you got it! You do operations, which set the flags for the conditionals to do things based on their state.
Let's chip away at it over time. Sometimes I have more, sometimes less, and others will jump in too.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
If so, no apology needed.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
Should we go through a simple loop?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!