Nanosecond frequency for an output pin
Jeffrey Kane
Posts: 48
Hello,
I am new to this, but i have an application that needs a frequency of 30 ns (nanoseconds), your viewport monitor seems to have the ability to get to 50 ns, , but the best i can get is 200 microseconds, do you have an example of code that would generate a frequency of 30ns? Sorry about the unsolved status, i'm sure this has been addressed before.
regards
Jeff
I am new to this, but i have an application that needs a frequency of 30 ns (nanoseconds), your viewport monitor seems to have the ability to get to 50 ns, , but the best i can get is 200 microseconds, do you have an example of code that would generate a frequency of 30ns? Sorry about the unsolved status, i'm sure this has been addressed before.
regards
Jeff
Comments
With a 5mhz crystal, it's easy to create a 12.5ns high with a 12.5 ns low by using one of cogs counter.
Is that good?, if not could go with a 4mhz crystal for 15.6ns+15.6ns
Though you could adjust the values in software, getting no jitter will be harder.
Producing pulses this short is problematic with the Propeller and other microcontrollers. You're trying to produce pulses on the order of the system clock time. You need to adjust the system clock frequency to be the same as your desired pulse frequency or related by an integer factor. Once you start dealing with custom crystal frequencies, you might as well just make an oscillator / counter to produce exactly what you need.
CON
_clkmode = xtal1 + pll16x
_clkfreq = 80_000_000
PUB main|hz,frame[6400]
dira[LEDs_START..LEDs_END]~~ ' Set entire pin group to output
repeat ' Endless loop
! outa[LEDs_START..LEDs_END] ' Change the state of pin group
' waitcnt(clkfreq /1000 'should give 1 millisecond
' waitcnt(clkfreq /1000000 + cnt) 'should give 1 microsecond
waitcnt(clkfreq /10000000 + cnt) 'should give 100 nanoseconds
so i used a scope and the best i get off the pin is about 200 microseconds
regards
Jeff
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
OBJ
vp : "Conduit" 'transfers data to/from PC
synth : "Synth"
qs : "QuickSample" 'samples INA up to 80Mhz
pub demoADC|freq,frame[1600] 'frame stores 1600 samples+configuration
vp.register(qs.sampleINA(@frame,4 )) 'sample INA with 4 cogs up to 80Mhz
vp.config(string("var:io(bits=[data[0],30tx,31rx]),freq(min=1,max=10000,unit=kHz),adc(min=-5,max=5,decode=io[0..0])"))
vp.config(string("spectrum:logx=false,bgnd=yellow"))
vp.config(string("dso:view=adc,timescale=200ns"))
vp.config(string("lsa:view=io,timescale=200ns"))
vp.config(string("edit:freq(default=2000,mode=dial)"))
vp.config(string("start:analog"))
vp.share(@freq,@freq)
repeat
synth.Synth("A",0, 1_000*freq)
Hanno
You could use assembly or spin to set up the counter output freq and output pin to get Fclk/2 or about 25.0ns as a fixed free running output. Then your code could change the counter parameters if a different freq was needed. Somewhere I have read you can clock over 100mhz using the pll function, but not guaranteed. If wrong, someone will be sure to put us right on this...... I use the counters for ADC/DAC timebase generator.
Frank.
'Propeller Programming Tutorial (from Propeller Manual Chapter 3)
{{FastestLed - was Output10.spin}}
'' 20080517 Ray Rodrick "Cluso99"
'' Pulses a pin at 100nS (5MHz xtal)
'' PulsePin_100nS.spin
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long Stack[9] 'stack space for new cog
byte Cog 'hold ID of cog in use, if any
PUB Main
Start(3) 'flash LED on Pin (0-31)
PUB Start(Pin): Success
{{Start new toggling process in a new cog; return TRUE if successful.}}
Stop
' Success := (Cog := cognew(FastestLed,Pin), @Stack) + 1)
Success := cog := cognew(@entry, @Pin) + 1
PUB Stop
{{Stop toggling process, if any.}}
if Cog
cogstop(Cog~ -1)
DAT
org
entry rdlong :pin,par 'get pin no. (0-31)
mov :pinmask,#1
shl :pinmask,:pin
mov dira, :pinmask
:wloop xor outa, :pinmask
jmp #:wloop
:pin res
:pinmask res
from my understanding, limited at best, each instruction takes 4 clocks, 50 ns so the loop uses two instructions therefore 100ns. I'll continue since i need to get to 25 ns square wave.
note: I used a scope on it and it is a very strange signal. the 100ns was correct but i expected a clean square wave, 0 to 3.3 volts but this was different, in the area where the voltage is usually a straight line this one had a lot of variance. probably +/- 1/4 volts, produced a rather fuzzy line. .
I was wondering if it would be easier to simply build a clock pulse generator circuit, since the clock is permanent and does not vary, the main work of this project is sending signal for varing control of a device (data channels) vs handling clock data, and to get where i think i need to go 25ns, i think i have to commit two cogs to the clock processing.
That is a strange spec that asks for a frequency of 30 ns - what exactly is it that, needs this ?
Analogs need a 10x speed to properly display a given square wave.
(A square wave consists of the original frequency and a whole lot of harmonics. Bl***dy noisy signal, really)
Admittedly, this is an odd approach with its own learning curve, but it is possible.
http://www.schmartboard.com/index.asp?page=products_csp&id=532
old, dusty scope, i have a new logic analyzer coming in, i'll check it again when it arrives. i'll implement the use of the counters today, see what i get.
the project needs, 30ns clock, 200 ns data lines (2), three 1 ms pulses (1 as a reference for data, 2 for hor and vert sync) some 3.3 power and ground.
i might end up with 2 propeller processors on the board, one will do clock related work, one will do data. I do alot of distributed work with multiprocessors, in the old days we used snoop line to interface between both processors, to sync the processors together, although there are other ways to do it. you could set up a small data channel with a few io pins. but i'll figure that out later.
everyone has been very helpful.
regards
Jeff Kane
The counters work as designed, interesting, a very powerful, flexable processor, Thank you for directing me in the correct direction.
This thread can be posted "solved", not sure I do this or the forum administrator.
regards
Jeff Kane
I believe you can just go to the first post in the thread, which you created, and edit it -- then you should be able to change the status to "solved".
You could also summarize what finally worked - ie what frequencies you created, with what precision and jitter, so that others reading this later can learn more ?
The work i am doing is all in the 25ns to 500us range, I'm stil working with the counters and perhaps a higher frequency clock. 6-8mhz, the only issue i am having currently is that viewport does not seem to accurately record at these speeds, so i have to go to aTLA5202 scope to validate the timings which slows down the testing.
vp.config(string("var:io(bits=[cntr[16..17],30tx,31rx]),counter(decode=io[16..17])"))
vp.config(string("lsa:view=io,timescale=1ms,trigger=io[16]r"))
vp.config(string("dso:view=counter,timescale=1ms/div"))
vp.config(string("start:lsa"))
but I do have one question on the resolution of the clock, although the clock runs at say, 80,000,000 (external 5mhz *16) which gives me a resolution of 0.0000000125, 12.5 ns, so each clock change adds 12.5, therfore i can get 25, 37.5, 50 ns and so on, but what if i need 33.3 ns? is there a way to slice the clock, or offset it, something like phases.
currently I can create an accurate 25ns, 200ns, 500ns 100us, and 200us with spin for the microsecond work and assembler for ns work.
for example:
cognew(@Toggle, @swStack[256]) ' timing markerscognew(@Toggle, @swStack[256]) ' timing markers
DAT
{Toggle P16}
org 0 'Begin at Cog RAM addr 0
Toggle mov dira, Pin16_17 'Set Pin to output
mov outa, Pin16_17 'Toggle Pin to high
mov Time, cnt 'Calculate delay time
add Time, #9 'Set minimum delay here
:loop waitcnt Time, Delay2 'Wait 125 us
xor outa, Pin16 'Toggle Pin
waitcnt Time, Delay1 'Wait 200 us
xor outa, Pin16 'Toggle Pin
waitcnt Time, Delay3 'Wait 100 us
xor outa, Pin17 'Toggle Pin
waitcnt Time, Delay1 'Wait 200 us
xor outa, Pin17 'Toggle Pin
waitcnt Time, Delay2 'Wait 125 us
jmp #:loop 'Loop endlessly
Pin16_17 long %00000000_00000011_00000000_00000000
Pin16 long %00000000_00000001_00000000_00000000
Pin17 long %00000000_00000010_00000000_00000000
Delay1 long 16_000 'Clock cycles to delay 200 us
Delay2 long 10_000 'Clock cycles to wait 250 us
Delay3 long 8_000 'Clock cycles to wait 100 us
Time res 1 'System Counter Workspace
it should look like
500us 200us 100us 200us
pin 16
|_____|
pin 17
|______|
regards
Jeff
If you only needed 33.3ns or a few other discrete frequencies, you could have multiple external clocks for the Propeller and some kind of multiplexor. The Propeller could switch to its internal clock long enough to change its external clock and allow that to stabilize, then switch to that.
If you need more variability than a few base timings and their multiples, you're not going to be able to do it with the Propeller. You'll need a well-designed digital signal generator, possibly with the Propeller acting as a controller.
do you have any suggestions (digital signal generator), I think i was heading that way, i have about 10 signals, mostly clocking, but fairly defined, what i am really doing is sending data, which is usually between 1ms and 500us, and it is variable, so the really task is the data, not the clocks, so moving it somewhere else if fine by me, and letting the propeller only deal with the control of the discrete signals and the data signals.
regards
Jeff
Are you taking in account the setup overhead every time you wait, better use interval waits instead.
What granularity and precision do you actually need.?
I have seen serial protocols that reduce the number of edges, by sending defined pulse widths and then they measure the widths to so many bits of precision. (eg 16 width steps can encode 4 bits etc )
http://humanoidolabs.blogspot.tw/2012/09/propeller-chip-nanotechnology-nano-probe.html
http://humanoidolabs.blogspot.tw/search?q=nano