You can get even more precision in Spin with the use of a counter (every cog has two of them).
The Spin code is smaller, but you need to know how the counter works to understand the code:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
us120 = 80*120 'cnt clocks for 120us and 20us
us20 = 80*20
pin = 0 'pin number to use
PUB Main : now
ctra := %00100<<26 + pin 'ctra in NCO mode
frqa := 1 'count up
phsa := 0 'output Low
dira[pin] := 1 'pin = output
repeat
now := cnt 'reference point for exact timing
phsa := -us20 'high for 20us
waitcnt(now += us120) 'wait until exactly 120us from reference point
phsa := -us20 'high for 20us
waitcnt(clkfreq/100+cnt) 'wait ~10ms before next loop
'
The pulses are now precise to 12.5ns, only the pause between the two pulses suffer still from the hub sync timing and can vary about 200ns. The minimal pulse time is now 12.5ns !!
So, if I have to mess with assembler anyway, than why should I choose "8 cores" instead of at least 5x cheaper solution, if I have to deal with ASM ?
As Mike pointed out, the Propeller instruction set is very nice, especially when it comes to fast, complex timing -- no cycle counting.
Based on your description, you desire to generate two pulses that could overlap, so it will be cleaner to use the counters to generate pulses. Using a counter in NCO mode is easy and gives you 12.5ns resolution at 80MHz. I wrote the code below (compiles, but I didn't bother testing -- you can do that) that allows you to call a .start() method with the parameters you want to use (pins and timing in microseconds); I'm not a fan of embedding pin #s in code as hardware designs frequently change. As you can see, after getting the parameters, io and counters setup, the code is quite simple.
var
long cog
pub start(in, out1, out2, pw, ho)
'' Start sensor/pulse generator cog
'' -- in, out1, and out2 are io pins
'' -- pw is pulse width in microseconds
'' -- ho is edge-to-edge hold-off in microseconds
stop
' convert pw (pulse width) and ho (hold-off) to system ticks
pw *= clkfreq / 1_000_000
ho *= clkfreq / 1_000_000
cog := cognew(@curious, @in) + 1 ' start the cog
return cog
pub stop
'' Stops cog (if running)
if (cog)
cogstop(cog - 1)
cog := 0
dat
org 0
' get parameters from hub
curious mov t1, par ' start of parameters
rdlong sensepin, t1 ' read input pin
add t1, #4
rdlong out1pin, t1 ' read pulse output 1
add t1, #4
rdlong out2pin, t1 ' read pulse output 2
add t1, #4
rdlong pulsetix, t1 ' ticks in pulse width
add t1, #4
rdlong hotix, t1 ' ticsk in hold-off period
' setup io
mov sensemask, #1
shl sensemask, sensepin ' convert pin to mask
mov out1mask, #1
shl out1mask, out1pin ' convert pin to mask
mov frqa, #1 ' setup ctra for hi-res pulse
mov phsa, #0
mov ctra, NCO_SE ' use NCO mode
or ctra, out1pin ' assign to out1
or dira, out1mask ' make out1 an output
mov out2mask, #1
shl out2mask, out2pin
mov frqb, #1
mov phsb, #0
mov ctrb, NCO_SE
or ctrb, out2pin
or dirb, out2mask
waitforinput mov phsa, #0 ' prevent spurious pulse
mov phsb, #0
test sensemask, ina wc ' look for input
if_nc jmp #waitforinput ' wait for high
mov sync, cnt ' establish sync point
pulse1 neg phsa, pulsetix ' pulse #1
add sync, hotix
waitcnt sync, #0 ' wait hold-off period
pulse2 neg phsb, pulsetix ' pulse #2
nop ' { may not be needed }
waitpne out2mask, out2mask ' let pulse #2 finish
jmp #waitforinput
' --------------------------------------------------------------------------------------------------
NCO_SE long %00100 << 26 ' for counters
sensepin res 1 ' input pin #
out1pin res 1 ' pulse output #1 pin
out2pin res 1 ' pulse output #2 pin
pulsetix res 1 ' ticks in pulse width
hotix res 1 ' ticks in hold-off period
sensemask res 1
out1mask res 1
out2mask res 1
sync res 1
t1 res 1 ' work vars
t2 res 1
fit 496
[Edit 1] It looks like Andy posted while I was writing my own version that uses counters. WAITCNT works in Spin and PASM, though with PASM there is far less overhead. If you look through my code you'll find it very straightforward; setting up the counter, for example, is nearly one-for-one, Spin to PASM.
[Edit 2] I've attached a ready-to-run demo that illustrates how the Propeller can be used for self-testing. This will allow you to connect nothing but a 'scope to verify the code is working. This is a simple example, but I do the same thing when writing new protocol drivers. THAT would be very hard to do on a small PIC.
Ah ... love it. One of the excellent reasons to use Parallax products rather than something a lot cheaper ... If you wait a bit, sometimes hours, sometimes a day or two, you'll get all sorts of diverse expert help.
Yes, the support from parallax community is the best so far. Contrary to Melabs guys, where you ask, "why this does not works" and get answer like "cause you're an idiot"
Thanks everyone for the code examples. Let's summarize:
Currently, parallax IDE, does not cares or checks whenever timings you specify in your code will be executed as you declared, if we're talking about microsecond delays.
Also, if your code requires parallel running of "cores", the compiler does not distributes the load across the cores, to get the high performance.
Parallax's IDE, whether the Propeller Tool or the GCC toolchain along with a number of 3rd party tools, do not do any kind of timing analysis at all, whether microsecond or millisecond. None of the Propeller programming tools care or check execution timings. In fact, there's no mechanism to declare them. There's no automatic "distribution" of computing across the cores. Both execution timing and control of the cogs (cores) is done manually. These are easy to do, but there's nothing automatic. This is deliberate. It's very difficult to do automatically, particularly with free or low-cost tools since the development costs are so high and the development time so long. Would you be willing to pay several hundred dollars for a programming tool ($600-$800) with some of the timing features you seem to want?
I can not see how a timing analyzer tool should know what you want to get. If you need to program in all the rules and timing parameters, you can also do a little Spin code in a second cog which analyzes your output, totally independent of the cog that generates the output.
A good example of a tool that does run an analyzer cog and show the output in a GUI on the PC is Hannos Viewport.
I know you will also find a fly in the ointment for Viewport. But this hurts only yourself and then you should perhaps change your Nickname to: UnsatisfiableOne
No name calling please. CuriousOne is looking for something specific that's not available for the Propeller nor for most microcontrollers on the market, certainly not as a free provided tool. There may be something done in academia as part of a thesis project. You might check out XMOS.
whilst our unique XTA static timing analyzer can be used to validate that all real-time requirements are met without the need for complex and time-consuming dynamic test suites
#include <xs1.h>
#define FLASH_PERIOD 20000000
out port led = XS1_PORT_4F;
int main(void) {
timer tmr;
int t;
tmr :> t;
while (1) {
led <: 0x1;
t += FLASH_PERIOD;
tmr when timerafter(t) :> void;
led <: 0x0;
t += FLASH_PERIOD;
tmr when timerafter(t) :> void;
}
return 0;
}
I personally liked the resolution of FLASH_PERIOD variable, but why so many brackets and commas, points and so on in C? why they make such strange syntax?
Most of it is standard C. Obvious exceptions include ":>" and "<:" and the when statement. You'll have to consult their C documentation for their extensions.
Basic was always intended to be a beginner's language.. that's why it was called Basic.
Precise usecond timing is not a beginner's project.
Why use 8 cores? Well if you have to have several events start and stop independent of each other, it is a lot easier than threaded code... may be the only good solution.
Why Propeller assembly versus PIC assembly? Well every time you need something different you might change PICs and have to learn a different assembler code and a lot of tedious detail about the silicon's architecture.
Why is Propller timing considered easier? For longer periods, a 32 bit counter makes it extremely easy to create long delays, where an 8 or 16 bit register structure might require a bit more complex code. And of course, for the smallest of delays, the Propeller generally runs faster than PICs. I am not sure that 12.5 nano-seconds is completely correct as instructions take 4 clocks. So 50.0 nano-seconds for most solutions is easily done. If you really need 12.5 nano-seconds, it may require something more sophisticated than I straight-forward one Cog solution.
Trying to buy a solution may work for awhile. But it you learn to code a solution, you will get persistent returns on your investment. Sure, you can get a PIC for $2 versus a Propeller for $10. But over the long haul, you may spend many more man-hours getting the right PIC for the job.
Indeed. As did others, I took time out of my life to write practical demonstration code and it turns out he doesn't even own a Propeller! I kind of wish forum threads were like Amazon book reviews where the review indicates if the reviewer actually purchased the book.
Also, if your code requires parallel running of "cores", the compiler does not distributes the load across the cores, to get the high performance.
Oi vey. This reminds me of a story told to me by a director (who also does electronics) about new employees in the visual effects world. They come into the office, sit down at their computer, and then proceed to ask, "Where's the dinosaur plug-in?" At some point you just have to put on your big-boy pants and build the dinosaur yourself. Counting on the work of others to completely automate your life is a fool's errand in my opinion. They don't put automatic transmissions in F1 cars for a reason.
Comments
The Spin code is smaller, but you need to know how the counter works to understand the code: The pulses are now precise to 12.5ns, only the pause between the two pulses suffer still from the hub sync timing and can vary about 200ns. The minimal pulse time is now 12.5ns !!
Andy
As Mike pointed out, the Propeller instruction set is very nice, especially when it comes to fast, complex timing -- no cycle counting.
Based on your description, you desire to generate two pulses that could overlap, so it will be cleaner to use the counters to generate pulses. Using a counter in NCO mode is easy and gives you 12.5ns resolution at 80MHz. I wrote the code below (compiles, but I didn't bother testing -- you can do that) that allows you to call a .start() method with the parameters you want to use (pins and timing in microseconds); I'm not a fan of embedding pin #s in code as hardware designs frequently change. As you can see, after getting the parameters, io and counters setup, the code is quite simple.
[Edit 1] It looks like Andy posted while I was writing my own version that uses counters. WAITCNT works in Spin and PASM, though with PASM there is far less overhead. If you look through my code you'll find it very straightforward; setting up the counter, for example, is nearly one-for-one, Spin to PASM.
[Edit 2] I've attached a ready-to-run demo that illustrates how the Propeller can be used for self-testing. This will allow you to connect nothing but a 'scope to verify the code is working. This is a simple example, but I do the same thing when writing new protocol drivers. THAT would be very hard to do on a small PIC.
Thanks everyone for the code examples. Let's summarize:
Currently, parallax IDE, does not cares or checks whenever timings you specify in your code will be executed as you declared, if we're talking about microsecond delays.
Also, if your code requires parallel running of "cores", the compiler does not distributes the load across the cores, to get the high performance.
Right?
A good example of a tool that does run an analyzer cog and show the output in a GUI on the PC is Hannos Viewport.
I know you will also find a fly in the ointment for Viewport. But this hurts only yourself and then you should perhaps change your Nickname to: UnsatisfiableOne
Andy
XMOS seems to have what I want:
http://www.xmos.com/products/tools/xtimecomposer
whilst our unique XTA static timing analyzer can be used to validate that all real-time requirements are met without the need for complex and time-consuming dynamic test suites
LOL but no BASIC language, only C & ASM
I personally liked the resolution of FLASH_PERIOD variable, but why so many brackets and commas, points and so on in C? why they make such strange syntax?
Precise usecond timing is not a beginner's project.
Why use 8 cores? Well if you have to have several events start and stop independent of each other, it is a lot easier than threaded code... may be the only good solution.
Why Propeller assembly versus PIC assembly? Well every time you need something different you might change PICs and have to learn a different assembler code and a lot of tedious detail about the silicon's architecture.
Why is Propller timing considered easier? For longer periods, a 32 bit counter makes it extremely easy to create long delays, where an 8 or 16 bit register structure might require a bit more complex code. And of course, for the smallest of delays, the Propeller generally runs faster than PICs. I am not sure that 12.5 nano-seconds is completely correct as instructions take 4 clocks. So 50.0 nano-seconds for most solutions is easily done. If you really need 12.5 nano-seconds, it may require something more sophisticated than I straight-forward one Cog solution.
Trying to buy a solution may work for awhile. But it you learn to code a solution, you will get persistent returns on your investment. Sure, you can get a PIC for $2 versus a Propeller for $10. But over the long haul, you may spend many more man-hours getting the right PIC for the job.
Seems XMOS has what you want. Good luck.
Indeed. As did others, I took time out of my life to write practical demonstration code and it turns out he doesn't even own a Propeller! I kind of wish forum threads were like Amazon book reviews where the review indicates if the reviewer actually purchased the book.
Oi vey. This reminds me of a story told to me by a director (who also does electronics) about new employees in the visual effects world. They come into the office, sit down at their computer, and then proceed to ask, "Where's the dinosaur plug-in?" At some point you just have to put on your big-boy pants and build the dinosaur yourself. Counting on the work of others to completely automate your life is a fool's errand in my opinion. They don't put automatic transmissions in F1 cars for a reason.
Good luck. Say "Hi" to Leon!
Thanks, Jon!!