ASM WAITPEQ help?
Sorry for the questions...unfortunately, I am not completely confident in my coding skills and need to rely on support right now.
Below I have simple code that uses WAITPEQ in both ASM and SPIN.
When I run this program with the ASM WAITPEQ commented out (and running the SPIN WAITPEQ), it works fine.· When I run the program with the SPIN WAITPEQ commented out (and running the ASM WAITPEQ), the rest of the program does not run.
Just to understand the program, I am monitoring PIN1.· When PIN1 goes high, I toggle PIN4 high and low 5 times.
It works when I use WAITPEQ in SPIN, but it is not working when I use the WAITPEQ in ASM.
Any help would be greatly appreciated.
Shaun
con
· _clkmode = xtal1 + pll16x
· _xinfreq = 5_000_000
pub Toggle_Main
···
WAITPEQ(%1, %1,0)
cognew (@Toggle, 0)
dat
······················· org······ 0
Toggle
············· WAITPEQ·· %1, #%1·
············· mov···· Counter, #5
············· mov···· dira,·· #10·············· 'Set Pin to output
············· mov···· Time,·· cnt··············· 'Place the value of cnt into Time
············· add···· Time,·· #9
·························
············
:loop
············· waitcnt Time,·· Delay············· 'Set Pin high
············· xor···· outa,·· #10··············· 'Toggle Pin
············· waitcnt Time,·· Delay············· 'Set Pin Low
············· xor···· outa,·· #10·············· 'Toggle Pin
············· DJNZ··· Counter, #:loop
············· jmp······ #Done
·············
·Done
············· mov······ outa, #00
············· jmp······ #Done············
·············
·············
Pin···· long··········· $10
Delay·· long··········· 1_000_000
Time··················· res 1
Counter················ res 1
Below I have simple code that uses WAITPEQ in both ASM and SPIN.
When I run this program with the ASM WAITPEQ commented out (and running the SPIN WAITPEQ), it works fine.· When I run the program with the SPIN WAITPEQ commented out (and running the ASM WAITPEQ), the rest of the program does not run.
Just to understand the program, I am monitoring PIN1.· When PIN1 goes high, I toggle PIN4 high and low 5 times.
It works when I use WAITPEQ in SPIN, but it is not working when I use the WAITPEQ in ASM.
Any help would be greatly appreciated.
Shaun
con
· _clkmode = xtal1 + pll16x
· _xinfreq = 5_000_000
pub Toggle_Main
···
WAITPEQ(%1, %1,0)
cognew (@Toggle, 0)
dat
······················· org······ 0
Toggle
············· WAITPEQ·· %1, #%1·
············· mov···· Counter, #5
············· mov···· dira,·· #10·············· 'Set Pin to output
············· mov···· Time,·· cnt··············· 'Place the value of cnt into Time
············· add···· Time,·· #9
·························
············
:loop
············· waitcnt Time,·· Delay············· 'Set Pin high
············· xor···· outa,·· #10··············· 'Toggle Pin
············· waitcnt Time,·· Delay············· 'Set Pin Low
············· xor···· outa,·· #10·············· 'Toggle Pin
············· DJNZ··· Counter, #:loop
············· jmp······ #Done
·············
·Done
············· mov······ outa, #00
············· jmp······ #Done············
·············
·············
Pin···· long··········· $10
Delay·· long··········· 1_000_000
Time··················· res 1
Counter················ res 1
Comments
WAITPEQ #%1, #%1
As both are literals.
Graham
You can't have a literal value in the destination field. The %1 means memory location 1. The easiest way to do this is to have another location, like "PinMask long %1" and then use "WAITPEQ PinMask,PinMask".· This will cause the cog to pause until pin zero is a logic one.· If you want some other pin, change PinMask.
Even when I assign Pinmask as a long = %1, and put in the 'WAITPEQ PinMask, PinMask' it still doesn't function correctly.
I have verified that it works in SPIN, but for some reason it is not functioning in ASM...
The below code can be verified by putting an oscope on Pin4, and toggling pin1 from low to high...
_______________________________________________________________________
Toggle
mov Counter, #5
mov dira, #10 'Set Pin to output
mov Time, cnt 'Place the value of cnt into Time
add Time, #9 'Add 9 to time
WAITPEQ PinMask, PinMask
:loop
waitcnt Time, Delay 'Set Pin high
xor outa, #10 'Toggle Pin
waitcnt Time, Delay 'Set Pin Low
xor outa, #10 'Toggle Pin
DJNZ Counter, #:loop
jmp #Done
Done
mov outa, #00
jmp #Done
Delay long 1_000_000
PinMask long %1
Time res 1
Counter res 1
______________________________________________________________
The problem is that I am able to get WAITPEQ in Spin to work.· When I have it in spin, the output is correct (See first picture· -· Top trace is me changing the state of Pin0 from Low to High, bottom trace is monitoring the output pin.)
When I put....
·______________________________
······· WAITPEQ· pinmask, pinmask
········ ....output code here.....···
······· Pinmask·· long·· %1
· _____________________________
....I am not changing any of the output code...The only change is putting in the WAITPEQ command.· The output code never executes (output pin toggling 5 times) with the ASM WAITPEQ.· See second picture.· The only thing that I am changing is where the WAITPEQ is...SPIN vs ASM.
Post Edited (Steel) : 7/13/2007 4:12:23 PM GMT
Another complication is that separate cogs have their own DIRA and OUTA registers. They're OR'd together among cogs to set the actual state of the I/O pin. Your Spin code and the assembly routine run in different cogs, so this affects what you're seeing.
In any event, WAITPEQ works in assembly the same way it works in Spin. What would be the "port" parameter is ignored in both Spin and assembly and the mask and compare state values work the same way. The example I wrote waits until the I/O pins marked by the mask (PinMask) are all one bits. To work properly, the direction register has to have those pins set as inputs (direction bit == zero) and no other cog can have those pins set as outputs.
Try it this way:
WAITPEQ PinMask, PinMask
mov Time, cnt 'Place the value of cnt into Time
add Time, #9 'Add 9 to time
Andy
here's the code I've been working with, its a little messy, but I'll leave it so you maybe can get an idea of what I was tryin to do
''Demonstration of PWM version of NCO counter mode CON _clkmode = xtal1 + pll16x _xinfreq = 6_000_000 VAR long parameter PUB go | x parameter := 50 'unused cognew(@entry, @parameter) 'start assembly cog DAT ''assembly cog fetches the value in parameter for PWM percentage org entry mov dira, diraval 'set pins to output or outa, ICGpin 'set ICG high to begin 'NOP mov 20, masterFreq 'copy masterFreq to register 20 shr 20, #4 'shift the contents of register 20 to the right by two places, divide by mov frqa, masterFreq 'set counter to increment 1 each cycle mov frqb, exposureTime 'set counter to increment 1 each cycle mov ctra, ctraval 'establish counter A mode and APIN ' NOP mov 18, exposureTime 'move current time to a register shr 18, #12 'divide exposure time a lot... seems weird, need to figure out this math mov 19, 18 'copy exposure time to reg 19 sub 19, #4 'subtract 4 (cpu cycles) from register 19 'mov 19, 18 'add 19, 18 mov ctrb, ctrbval 'both counters are now going, master clock and SH line 'add 19, CNT 'add the exposure time to the current register NOP :ccdStart 'andn outa, ICGpin 'mov 21, numActivePixels 'mov 17, #0 'needed a register that held 0 for waitcnt 'waitcnt 17, 18 'wait til 0 on the counter, add 1/2 exposure time (from register 18) 'add 17, 18 'now 17 should hold exposureTime worth of cpu cycles 'waitcnt 17, 18 'wait til 1/2 exposure time, add 1/2 exposure time waitpeq SHsensePin, SHsensePin 'NOP andn outa, ICGpin waitpeq SHsensePin, SHsensePin 'NOP 'waitcnt 17, 18 'NOP or outa, ICGpin jmp #:ccdStart ':pixelLoop 'waitcnt 17, 20 'djnz 21, #:pixelLoop 'or outa, ICGpin 'jmp #:ccdStart' rdlong value, par 'get an up to date pulse width 'waitcnt time, period 'wait until next period 'neg phsa, value 'back up phsa so that it trips "value" cycles from now 'jmp #:loop 'loop for next cycle diraval long |< 6 | 1<<8 | 1<<7 'Direction of pin 6,7,8 == outputs ctraval long %00100 << 26 + 7 'NCO/PWM APIN=7, master clock ctrbval long %00100 << 26 + 6 'NCO/PWM BPIN=6 SHpin long 1<<6 SHsensePin long %10000 'this is just a physical loopback from SHpin ICGpin long 1<<8 period long 96 '1000kHz period (_clkfreq / period) masterFreq long 134217728 'master CCD frequency, ~3Mhz exposureTime long 4194304 '~10uSecs fourExposureTimes long 16777216 halfExposureTime long 2097152 numActivePixels long 3648 maxVal long $FFFF time res 1 value res 1
http://forums.parallax.com/showthread.php?134454-Need-waitpeq-examples&p=1035440&viewfull=1#post1035440
waitpeq SHsensePin,SHsensePin andn outa,ICGpin waitpeq SHsensePin,SHsensePin or outa,ICGpin
The andn instruction takes 4 clocks, the following waitpeq takes a minimum of 5. Using a 6MHz xtal with 16x PLL that's one instruction every 10.4ns, so approximately 94ns from one waitpeq to the other. If SHsensePin is high for longer than 94ns the routine will set ICGpin high right after setting it low ... is that what you intended? If you're looking for SHsense to transition, you need to insert a waitpne to detect a low before using waitpeq to detect a following high.I don't see how the Z flag is used at all in this routine.
baaaad!
1. Not a good idea to hijack the thread of someone else
2. The code you posted ..... brrrrr
You should not use direct addresses in your instructions. This is simply not maintainable code! You uncomment one line of code and have to shift all the direct addresses manually. If you constantly use labels the compiler takes care of that! If I counted right 18 is exactly where you placed the label diraval. Is this intended?
If I see it right you want to reuse a register after it's no longer needed, but you want to avoid using that label?!
Then you should know that you can set as many labels for one memory location as you want:
label1
label2
label3 long 1234
All 3 labels point to the same long! So, please use meaningfull labels also for the temporary registers - something like tmpcalc1
Mike,
The statement that "no other cog can have those pins set as outputs" is not entirely correct. In the attached bit of code, I am using a separate cog for timing generation. The cog using WAITPNE and WAITPEQ monitors the pin to determine when the chip select is high and then when the chip select has gone low to begin sampling on an MCP3201 ADC.
Better to say watch out for where you set pins to output highs on the cog executing the WAITPXX since logic highs rule in the ORed scheme of prop I/O. If a WAITPEQ is looking for a low (maskbit=0), it will wait until the pin goes low to continue and if the cog waiting set the pin high prior to the WAITPEQ running, it will wait forever as the pins are now permanently unequal and there is no way to clear the pin to low. For WAITPNE, if the test is set to look for a high bit (maskbit=1), if the pin is low, passes through, but if the input gets set high on the pin in question prior to the WAITPNE executing, again the cog will wait forever since now they are always equal.
main waitpeq cselp,cselp ' wait for csel high waitpne cselp,cselp ' when csel goes low, start acq capture/store cselp res 1 ' will contain 1 where the chip select is assigned. (%0---01 say for pin 0 monitoring) Passed in via PAR+4(N)
As I understand it and it worked for me,
Frank
Ohhhh, that's a good point. SHpin is timer B's pin, which I literally have a wire looping from it to SHsensePin, Its 50% duty @ ~10 microsecond period
Is that a rule here? This is a 5 year old thread, how am I hijacking anything? If you would have posted this question to a new thread, would you have told me to "try using the forum search before asking questions"?
Its just keeping information aggregated, google already has this page linked in their database, people may have quoted this page on blogs, code, etc...
Hmm, no, that wasn't intended. I didn't know those longs were in registers... are they really? Why isn't that on the stack? (or doesn't the propeller work like that!???)
good to know, thanks.
yeah... I'm just learning Assembly for the first time because I want to use the propeller (I don't know spin either, though I'm getting familiar with the function and register vocabulary, etc..
Its not C!
"... would you have told me to "try using the forum search before asking questions"? ... My feeling is that nobody here would have said something like this! There are a lot of questions that come again and again and I can't remember a thread where someone has been blamed for not using the forum search - at least not in the same way as they do this in other forums. Most propable reaction would be to answer the thread pointing you the other thread where this question has been asked before.
The propeller does not have registers like other microprocessor designs. The propeller only has COG-RAM! Each COG-RAM can be anyting, a variable that contains a value, a variable that contains a pointer inside COG-RAM, a variable that contains a pointer to HUB-RAM ... you can do calculations with each COG-RAM long ...
In other words all the COG-RAM that is not occupied by code can be used as a register for storing whatever you need to store.
mov x,y
long 10
both will occupy one long in the COG-RAM in the order you use them in your program.
A technique I often use is to have an initialization-routine which by nature only runs once and then I reuse those COG-RAM positions for doing temporal calculations or for keeping loop-counters .... And then it makes sense to use the multi-label feature to write readable, self-explanatory code. For example:
dat org 0 temp Init mov hub_pointer_par1, par add hub_pointer_par2, par mainloop rdlong temp , hub_pointer_par1 rdlong temp+1, hub_pointer_par2 ' do something jmp #mainloop hub_pointer_par1 long 0 hub_pointer_par2 long 4
"good to know, thanks." - you're welcome!