Shop OBEX P1 Docs P2 Docs Learn Events
How to use smartpin to make 24 MHz? — Parallax Forums

How to use smartpin to make 24 MHz?

Has anyone worked out the math?
I need a 24 MHz clock to feed to a camera module...

I'm trying to figure out these SmartPin instructions:
%00110 = NCO frequency

This mode overrides OUT to control the pin output state.

X[15:0] establishes a base period in clock cycles which forms the empirical high and low times.

Y[31:0] will be added into Z[31:0] at each base period.

The pin output will reflect Z[31].

IN will be raised whenever Z overflows.

During reset (DIR=0), IN is low, the output is low, and Z is set to zero.

I guess it wouldn't be too hard if period were even number of clocks, but I need a period of 3-1/3 clocks...
«1

Comments

  • rjo__rjo__ Posts: 2,114
    Start_Xclk 'thank you Ozpropdev!!!
    WRPIN #%1_00110_0,#_Xclk
    WXPIN #1,#_Xclk
    qfrac ##xclk_freq,##sys_clk
    getqx pa
    WYPIN pa,#_Xclk
    dirh #_Xclk
  • rjo__rjo__ Posts: 2,114
    not sure this works for 24MHz... Using an 0v7670, which is supposed to give a frame rate as a function of clock frequency everything is ducky right up to 20MHz and then it isn't.

    this code for the ov7670 and ov7675 works at 20MHz but not for 24MHz... I went back to the 120MHz P2 version, it didn't work either ... but not sure if that was before or after I damaged my poor little P123... such a nice board:(

  • RaymanRayman Posts: 13,797
    Thanks! I'll give it a try. I can check with scope...
  • rjo__rjo__ Posts: 2,114
    I love the 7675, but I'm convinced that the ones floating around on the internet are spoils. The data sheet says that there is 8 pixel padding on either side of href, but I'm convinced that the pixel arrays on all my boards include the padding and skips some active pixels. As though someone miscalculated an offset. There is also an issue with the size of the pixel array... If I try to get all 480 lines, then the Vsync gets missed... 479 works. It may be my code... and maybe I have stared at it too long.

    This code works around the issues.



  • RaymanRayman Posts: 13,797
    Thanks, I'll check it out.
    Looks like you beat me to it...
  • RaymanRayman Posts: 13,797
    I need to check the 24 MHz at work with a better scope.
    Seems to be too fast for my scope at home...
  • evanhevanh Posts: 15,126
    Here's the 24 MHz version:
    mode001000005.PNG
    640 x 480 - 18K
  • evanhevanh Posts: 15,126
    edited 2017-11-25 00:03
    It'll be alternating between 4 sysclocks for 20 MHz and 3 sysclocks for 26.6667 MHz. The average frequency is bang on ... but not much good for a stable digital clock.

    Is 26.6667 MHz close enough?
  • RaymanRayman Posts: 13,797
    edited 2017-11-25 00:02
    Eeek! That's no good. I think it violates the clock duty cycle spec... Maybe that's why rjo__'s works at 20 MHz and not 24 MHz...

    20 MHz is good enough, I think...
  • evanhevanh Posts: 15,126
    Rayman wrote: »
    Eeek! That's no good. I think it violates the clock duty cycle spec...

    Ah, I have an idea, it's likely to be just the variance in the rising times rather than duty as such ... With some experimenting I see even this idea needs the duty (instead of frequency) mode set:
    Start_Xclk              'thank you Ozpropdev!!!
                        WRPIN #%1_00111_0,#_Xclk
                  	    WXPIN #1,#_Xclk
                        qfrac ##26_666_667,##sys_clk
                        getqx   pa
                        WYPIN pa,#_Xclk
                        dirh #_Xclk
                               ret
    
  • evanhevanh Posts: 15,126
    Here's 26.667 MHz in duty mode, I think it'll work fine.
    mode001000007.PNG


    And here's 24 MHz in duty mode. It's cleaner than frequency mode but still no good for steady clocking:
    mode001000006.PNG
    640 x 480 - 19K
    640 x 480 - 19K
  • evanhevanh Posts: 15,126
    Actually, neither of those modes are desirable. They are only meant to be used for averaging the pulse rate.

    The better mode is PWM sawtooth mode (%01001). It is defined in terms of the number of clocks for the period. There's no accumulative rollover happening:
     		dirl    #tpin                     ' Disable Smartpin while setting up
    		wrpin   #%01_01001_0, #tpin       'PWM sawtooth mode
    		wxpin   ##$30001, #tpin           ' 3 sysclocks for period = 26.667 MHz
    		wypin   #2, #tpin                 ' Duty is 2 high, 1 low
    		dirh    #tpin                     ' Enable Smartpin
    
    		jmp     #$
    
  • It's a pity the fractional clock feature of the aysnc serial modes can't be used in some way for a tighter NCO frequency mode.
  • jmgjmg Posts: 15,140
    ozpropdev wrote: »
    It's a pity the fractional clock feature of the aysnc serial modes can't be used in some way for a tighter NCO frequency mode.

    The edge placement is always going to be SysCLK granular, no matter what clock derivation is used.
    I think the Serial modes restart on every frame, to avoid the 2^32 round-over effect NCO otherwise has.
    ie NCO does not actually give precisely 24MHz,

  • evanhevanh Posts: 15,126
    edited 2017-11-25 07:11
    Wow, what a mode! It's not doing the impossible but a valiant effort for async comms. It is throwing intentional jitter, a dither I guess, into the bit timing to keep it evened out.

    Locking onto it with the scope was weird. It can look surprisingly clean with overlaid waveform averaging turned on. Worst case is not surprisingly at the fastest clock rates. Top limit is 40 Mbit/s on 80 MHz sysclock - which can then emulate up to a 20 MHz clock.

    The commented out 48 Mbit/s line produced a solid 80 Mbit/s rate (clean 40 MHz waveform).

    Here's my test source code:
    		waitx   one_sec
    'set mode of Smartpin
    		dirl    #tpin                     ' Disable Smartpin while setting up
    
    		wrpin   #%01_11110_0, #tpin       'Asynchronous serial transmit
    '		mov     parm, ##$1A800            ' bitrate = 48 MHz = (1.666667 * $1_0000) & $FFFFFC00
    		mov     parm, ##$35400            ' bitrate = 24 MHz = (3.333333 * $1_0000) & $FFFFFC00
    '		mov     parm, ##$20c00            ' bitrate = 39 MHz = (2.051282 * $1_0000) & $FFFFFC00
    		or      parm, #$1F                ' 32N1 protocol
    		wxpin   parm, #tpin
    		call    #itoa
    		call    #putnl
    
    		dirh    #tpin                     ' Enable Smartpin
    
    		mov     parm, ##$55555555         ' Emulate clock pattern
    		wypin   parm, #tpin
    .peas
    		testp   #tpin      wz
    if_z	wypin   parm, #tpin               ' Keep feeding the serial port with more emulated clocks
    		jmp     #.peas
    

    Here's a 24 Mbit/s output ( emulating a 12 MHz clock). This screenshot is with waveform averaging enabled to clean up the jitter. It looks very stable like this but you still get to see where the jitter is though, the stepped notches in the waveform is how far the jitter fluctuations are moving.
    mode001000010.PNG
    640 x 480 - 19K
  • evanhevanh Posts: 15,126
    edited 2017-11-25 10:35
    Bah! The async serial pacing is the same NCO function as the opening 24 MHz except it can't go that fast so it's not as obvious.

    It doesn't take that much of a down clock for NCO to look okay for databus operations. EDIT: That doesn't mean it is okay though. Eg: The camera probably uses the clock internally and needs it stable more than a particular frequency.

    On the flip side, async serial never locks to a clock so dithering the bitstream is perfectly viable.
  • Some NCOs offer a second, tuning parameter to add another factor into the counting.
  • @rjo__

    I tried your above code I get loading errors. Am I missing something?
    968 x 811 - 52K
    791 x 856 - 47K
  • Might be beating a dead horse here, but...
    Has anyone gotten this to work?
    I don't need the bitmap, but there are issues with the sample code:
    (1) clkset isn't a valid op, what do I use instead?
    (2) What pins are used to connect to the VGA monitor? My understanding is that I need 8 pins to drive the VGA signals.
  • Cluso99Cluso99 Posts: 18,066
    wmosscrop wrote: »
    (1) clkset isn't a valid op, what do I use instead?
    from the top level spin you set the clock
      _clkfreq = 297_000_000
    
    from pasm
    		rdlong	pa,#@clkfreq			'calculate streamer frequency
    
    (2) What pins are used to connect to the VGA monitor? My understanding is that I need 8 pins to drive the VGA signals.
    5 consecutive pins are used starting on an 8 pin boundary. IIRC they are in order HS, B, G, R & VS.

    I have a modified driver that uses a 4 pin boundary for HS, B, G, R and VS is 1 pin below the 4 pin group. So it uses the upper 5 pins of an 8 pin group.

    Probably best to look at the VGA demos downloaded with pnut.
  • evanhevanh Posts: 15,126
    edited 2020-12-09 03:23
    That would've been v32, revA, or earlier design files for the FPGA. The CLKSET $FF (later renamed to HUBSET) is for FPGA only (specifies 80 MHz sysclock), and the revA streamer modes are all different to revB/C too. That looks to be about it though.

  • RaymanRayman Posts: 13,797
    It's been a while but I think the stuff here can do it:
    https://forums.parallax.com/discussion/172393/nco-square-wave-output-using-smartpin
  • evanhevanh Posts: 15,126
    Here's example of translating the streamer modes. This:
    m_bs		long	$CF000000+16		'before sync
    m_sn		long	$CF000000+96		'sync
    m_bv		long	$CF000000+48		'before visible
    m_vi		long	$CF000000+640		'visible
    
    m_rf		long	$7F000000+640		'visible rlong 8bpp lut
    

    becomes this:
    m_bs		long	$7F010000+16		'before sync
    m_sn		long	$7F010000+96		'sync
    m_bv		long	$7F010000+48		'before visible
    m_vi		long	$7F010000+640		'visible
    
    m_rf		long	$7F080000+640		'visible rlong 8bpp lut
    
  • I can say the NCO mode is only good to 1 MHz or so, if you are careful and clever you might get several clean MHz out of the P2 chip. I am the process of designing a Shortwave and SSB ham radio transceiver. It will use an IF in the upper 40 MHz region, way beyond the capabilities of the P2 chip. I tried the 3-channel Si5351 synth chip. It is "just" OK, but the register math is a bit much to do correctly. Currently I am using the Si570 synth chip with all the bells. Again it works but the register math is a bit much to do correctly. Most if not all the synth examples published are not correct, or incomplete. The P2 at least has a decent 64-bit divide & multiply command which makes life much easier. My 2c worth.
  • Have a look here for some code to operate the Si5351 over a wide frequency range.
  • bob_g4bbybob_g4bby Posts: 401
    edited 2020-12-09 22:16
    I'm currently rewriting the prototype Peter mentions, now that's reliable. The aim is to do as little all-integer calculation as possible when a frequency change occurs, and send only changed register values to the si5351, using address autoincrement where possible. This, to sound like an analogue vfo as much as is possible. No 'arpeggio' noises when spinning the dial, because the frequency isn't being updated fast enough.

    Cheers Bob G4BBY S.W. UK
  • for Bob G4BBY - I always use the latest version of SPIN2 and in this case Version 2.4r3
    I did some revised / improved code on the Si5351, as most every example on the Internet and even the manufacturer were either wrong or incomplete. Going thru every single rule and register, I have a rather complete PUB functions. You need a good 64-bit SPIN2 multiply & divide function to do it right because you are taking the answers out to the last digit & errors crop up. Plus you do not want to take any short cuts in the code because you never know when a register will change. The P2 is so fast you can calculate each and every frequency change in real time, you never notice any jumping or anything. I gave up on the Si5351 because the smallest increment is at least 100 Hertz, not good for radio work. I will post what I have later.

    Currently I am using the much better Si570 synth chip. Again most every example on the Internet is wrong or incomplete including the example on SI website. I do a complete recalculation ( Micro-seconds ) for every frequency change, because you really never know when a register will change - The register math is something else!!! You need a really good SPIN2 64-bit Multiply & Divide function to get it right. I will share the PUB functions later.
  • jmgjmg Posts: 15,140
    edited 2020-12-10 00:44
    PropGuy2 wrote: »
    .. I gave up on the Si5351 because the smallest increment is at least 100 Hertz, not good for radio work. I will post what I have later.

    Currently I am using the much better Si570 synth chip..
    I'm curious about the 100Hz comment - the Si5351A allows register settings finer than 1Hz at 14MHz, but were you meaning a usable-practical limit of 100Hz ?
    The Si5351A can end up using quite large integer-fraction ratios for the M feedback, and that could give more spurs ?

    The Si570 has much higher VCO ( ~ 5GHz) than Si5351 (600~900MHz) so it will have better spectrum - but the mature Si570 comes only in 5x7 cases.
    The Si514 is between the two, with lower Icc and smaller packages than Si570, and similar jitter specs to Si570.
    The Si549 has ~ 11GHz VCO and even lower jitter than Si570, but there seems less info out there on Radio use examples of Si514 or Si549.
    Stocks are showing of Si514 & Si549.

  • Yes the practical limit on frequency increments is about 100 Hz, lucky to get 50Hz resolution. Plus the Si5351 is known to have jitter and spur problems. this is not good for RF circuits in the Short wave / Ham bands with IF frequencies in the 45MHz range.The other problem is it comes in the M10 footprint, too small for my eyes.

    The Si570 is a good choice all around for RF circuits. The 5x7 footprint is doable on a PCB. The frequency resolution is good - if you can get past the register math. It took me a couple of weeks to figure it out LOL Other synth chips are out there but I need something reliable that I can work with - and not spend days or weeks plowing thru bad documentation and poor code examples.
  • bob_g4bbybob_g4bby Posts: 401
    edited 2020-12-10 14:23
    Propguy2,

    Between 100 - 50Hz resolution? - Do you mean you cannot tune the SI5351 in less than 50Hz steps or that frequency accuracy is more than 50Hz adrift at certain frequencies?

    I've been checking my set up with an old Racal frequency counter which limits measurements to 30MHz. After correcting the crystal frequency constant in the software, o/p accuracy varies with demanded frequency and PLL frequency setting, but seems better than 10Hz. I was having too large step size issues at one point. I wrote a check function that calculated the output frequency from the params A,B,C etc which revealed a maths error. After fixing that, the chip tuned smoothly in hardly discernible increments, when monitored in a receiver. The check frequency was at worst 4Hz away from the demanded frequency, worst case being at the 120MHz end of course. Precision seems to be OK with me, at least. One of my functions uses a 64 bit intermediate value in a multiply-divide step too.

    My listening experience over several years with a Proficio sdr tuned with an SI5351 has been very good with regard sensitivity, selectivity and lack of spurs (much fewer spurs than the DDS tuned Flex 3000 ), so for me SI5351 performance seems good enough. The SI5351 is operated in the frequency range 6-120MHz, with an external divide by 4 to drive a tayloe mixer with quadrature signals at 1.5 - 30MHz. I also note Elecraft have designed the SI5351 into their KX2 and KX3 radios which are well respected. Both these applications are different from a superhet with 45MHz IF of course, especially if the LO is set on the high side, so you'd need the SI5351 to tune 46.5 - maybe 75MHz? I can see how the SI570 might start to pull ahead on performance in that range.

    "you never know when a register will change" Agreed, they change in a complicated way. I save a few key parameters from the last cycle and compare them with the newly calculated parameters as I'm writing to the SI5351. If the new and old byte are the same I don't resend it. Sending an i2c byte is relatively slow, so I've chosen to avoid it - the aim being that whilst tuning around with a rotary control, a lot of the time only 1 to 3 bytes need sending every frequency change. I haven't completed it yet - and it'll be worth comparing the tuning rate with that and more simple register loads. The added logic may take longer (in forth) than a more simple load, we shall see.

    All the best with your receiver project, of course.






Sign In or Register to comment.