Shop OBEX P1 Docs P2 Docs Learn Events
How to enable NCO_FREQ on pin? — Parallax Forums

How to enable NCO_FREQ on pin?

I'm trying to generate a 3.7 MHz clock on a P2 SmartPin, for an external device. I've set my _clkfreq to 40x that value, and have Spin2 functions in my main module that call PINSTART and PINCLEAR, plus some support. My crystal is 5 MHZ. Nothing happens when I call PINSTART.


CON
'142,848,000 Hz is the SAM 3.5712 MHZ clock times 40
_clkfreq = 142_848_000 'sets clock PLL. Compilation fails with impossible numbers > 500 MHz.
'SAM
pLLIOSamRst = 43
pLLIOSamClk = 42
pLLIOSamIo1 = 40
pLLIOSamIo2 = 39
pLLIOSamIo3 = 41
PUB SamStart() : RESULT | mode
'Start clock on PIO42 at 3.5712 MHz
'See SmartPin Supplement, search "%00110: Numerically Controlled Oscillator (NCO)"
DIRb.[pLLIOSamRst-32] ~~ 'RST PIO 43. dirA[42] does not work. dirB[0] is PIO32. dirB[11] is PIO43.
OUTb.[pLLIOSamRst-32] ~ 'RST low
DIRb.[pLLIOSamClk-32] ~
'PINSTART(PinField, Mode, Xval, Yval)
' ASSUME _clkfreq is 40X the desired SAM clock.
'mode := %0000_0000_000_0000_000000000_01_00110_0
PINSTART(pLLIOSamClk, P_OE | P_NCO_FREQ, 40, 0)
'PINH(pLLIOSamClk)
{{
ORG
NCO_Config long %0000_0000_000_0000_000000000_01_00110_0
dirl #42
wrpin NCO_Config,#42
wxpin #40,#42
wypin #0,#42
dirh #42
END
}}
RESULT ~
OUTb.[pLLIOSamRst-32] ~~ 'RST high
fourrdrs.str(k4RdrHost, string("SamStart complete",13,10))
PUB SamStop() : RESULT
OUTb.[pLLIOSamRst-32] ~ 'RST low
'Stop clock on PIO42 and ground it
PINCLEAR(pLLIOSamClk)
DIRb.[pLLIOSamClk-32] ~~
OUTb.[pLLIOSamClk-32] ~~
RESULT ~
fourrdrs.str(k4RdrHost, string("SamStop complete",13,10))

After calling SamStart(), the clock pin is steady 0V. After calling SamStop, it is steady 3V3. So I have control of the pins as I/O points, and proof that the line is not shorted to ground, but I can't get the function to generate.

I tried it in assembly in case that was necessary - didn't help. I thought my problem might be in the main module, but @Wuerfel_21's example https://forums.parallax.com/discussion/175884/e-guitar-synthesizer-in-50-lines-of-spin-2 has the PINSTART call right in main. I tried PINH after PINSTART. I included the Output Enable constant. And of course I'm using the serial port examples with PINSTART. I've tried different X and Y values to try and make something happen. But nothing happens.

Can someone spot my mistake? Thanks!

Comments

  • Well that's certainly not how it works.

    • The NCO frequency value goes in Y, not X
    • NCOs are not frequency dividers - the frequency value is a binary fraction of clkfreq, so 40 will be very slow

    For an exact divider, you'd use P_PULSE. Something like pinstart(..., P_PULSE|P_OE,40 + (20<<16),1234) where the Y value (1234) is the number of pulses you want. You can keep writing large numbers into Y if you want to pulse indefinitely.

  • JonnyMacJonnyMac Posts: 9,378
    edited 2025-07-09 20:31

    I'm trying to generate a 3.7 MHz clock on a P2 SmartPin, for an external device.

    This works -- but I may be missing something

      freq := 3_700_000
      pinstart(TEST_PIN, p_nco_freq | p_oe, 1, freq frac clkfreq)
    

    Here's the logic analyzer capture:

    My P2 projects run at 200MHz.

    Edit: I just noticed that you're running at 142_848_000. The smart pin code above still produces the correct output. Hat tip to @Ariba to showing me how to use the smart pin to generate a specific frequency using NCO mode.

  • It's working now, of course:

    PINSTART(pLLIOSamClk, P_OE | P_NCO_FREQ, 1, 3_517_200 frac _clkfreq)

    I took JonnyMac's answer so I wouldn't have to learn about pulses right now. Thanks again, both of you.

    For the record, the SmartPin Supplement says:

    %00110: Numerically Controlled Oscillator (NCO)
    The value X[15:0] (0 < n < 65,536) presets a 16-bit divide-by-n counter that produces an
    output--a base frequency--referenced to the system-clock frequency. To divide the
    system-clock frequency by 2, set X = #2.
    The Y register (Y[31:0]) holds a value that gets added to a 32-bit value in the Z register
    (Z[31:0]) at the start of each base period.

    Which led me to put a divisor in X and 0 in Y.

  • RaymanRayman Posts: 15,365

    It'd be nice if there were a web based tool for smartpin type stuff, where you just select what you want and it spits out the code...

    But, maybe AI will take care of that for us?

  • evanhevanh Posts: 16,585

    That "supplement" should probably be removed. It has many errors. Read Chip's original Silicon Doc instead - https://docs.google.com/document/d/1gn6oaT5Ib7CytvlZHacmrSbVBJsD9t_-kmvjd7nUR6o

Sign In or Register to comment.