Shop OBEX P1 Docs P2 Docs Learn Events
P2 PASM PWM with NCO — Parallax Forums

P2 PASM PWM with NCO

Hello,
I am looking for an example in PASM about this:

%00111 = NCO duty
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-time and low-time units.
Upon WXPIN, X[31:16] is written to Z[31:16] to allow phase setting.
Y[31:0] will be added into Z[31:0] at each base period.
The pin output will reflect Z overflow.
IN will be raised whenever Z overflows.
During reset (DIR=0), IN is low, the output is low, and Z is set to zero.

So I can understand this better.
Thanks

Comments

  • JonnyMacJonnyMac Posts: 9,102
    edited 2021-03-16 02:42

    This is general form of configuring a smart pin -- this is what the Spin2 function pinstart() does.

                    fltl      pin
                    wrpin     mode, pin
                    wxypin    xval, pin
                    wypin     yval, pin
                    drvl      pin
    

    You need to use the P_OE flag in the mode setting so that the pin will be driven high and low by the smart pin configuration.

  • pic18f2550pic18f2550 Posts: 400
    edited 2021-04-16 14:16

    Can I synchronise my programme with it?

    setse1 #%001<<6 + pin
    .......
    waitse1 'wait for new period
    
    dat
            org 0
    
            dirl #20                                '' Setup Smart Pin at P20
            wrpin PulseConfig, #20                  '' Set config for pulse/cycle
            wxpin PulseTiming, #20                  '' Set cycle time and logic-0
                                                    '' period
            dirh #20                                '' Finished setup
    
            setse1 #%001<<6 + 20
    
            wypin Cycles, #20                       '' Pulse count to Y register
            nop                                     '' Delay two clocks for IN to drop
    .myloop
            waitse1                    ''wait for new period
            '' code
            jmp #.myloop                            '' Program waits forever
    
    PulseConfig long %0000_0000_000_00000_00000000_11_00100_0
    
    '' Pulse/cycle mode
    Cycles        long $0010                        '' Pulse count of 16
    PulseTiming   long $01F4_05DC                   '' 60 usec pulse, 20 usec logic-0
                                                    '' [15:0 ] Loop Zeit (Zyklus]
                                                    '' [31:16] Pulszeit
    
  • AribaAriba Posts: 2,690

    You need to clear the flag after every waitse1. You also have not set the mode right.
    This version should work:

    dat
            org 0
    
            dirl #20                                ' Setup Smart Pin at P20
            wrpin PulseConfig, #20                  ' Set NCO duty mode
            wxpin PulseTiming, #20                  ' Set precounter and phase
            dirh #20                                ' Finished setup
    
            wypin Freq, #20                         ' Pulse freq to Y register
            setse1 #%001<<6 + 20                    ' set posedge event
    .myloop
            waitse1                                 ' wait for new period
            akpin  #20                              ' clear flag
            ' more code
            jmp #.myloop                            ' Program loops forever
    
    PulseConfig long %0000_0000_000_00000_00000000_01_00111_0  'OE + NCO duty
    
    ' Pulse/cycle mode
    Freq          long 1 frac 2500                  ' Pulse rate: ~100ms
    PulseTiming   long 0<<16 + 1000                 ' 1/1000 sysclock (~25kHz)
                                                    ' [15:0 ] Vorteiler
                                                    ' [31:16] Zählerwert bei Start
    

    But I think this is not the mode you want. It's not a usual PWM. The Duty mode has a fixed high time (here) and varies the low time to modify the duty, so the frequency changes with duty. For PWM there are better smartpin modes (triangle and sawtooth pwm).

    Andy

  • Ok, sawtooth PWM could actually be better.
    I want to output a variable pulse on a constant time grid. 0...100%.
    Do you have a code snippet for me to better understand?

  • JonnyMacJonnyMac Posts: 9,102
    edited 2021-04-16 18:51

    I know you're going to do this in PASM -- but here's how I do it in Spin.

        x.word[0] := 1 #> ((clkfreq / hz) / units) <# $FFFF 
        x.word[1] := units    
        pinstart(pin, P_OE | P_PWM_SAWTOOTH, x, duty)  
    

    In my simple code I allow the user to specify PWM frequency and the units in 100%. With LED dimming, for example, I specify units of 255 to match DMX lighting control. You could certainly set your units to 100 for 1% resolution. Note that you can change the duty at any time, but it will take effect on the next PWM cycle.

  • JonnyMacJonnyMac Posts: 9,102
    edited 2021-04-16 19:18

    Before popping out to get some lunch I knocked this together and it works! (verified with 'scope)

    con
    
      CLK_FREQ = 200_000_000                                        ' system freq as a constant
    
      _clkfreq = CLK_FREQ                                           ' set system clock
    
    
    con
    
      PIN   =      0
      HZ    = 10_000  
      UNITS =    100
    
      XREG  = (UNITS << 16) | ((CLK_FREQ / HZ) / UNITS)  
    
    
    dat
    
                    org       0
    
                    asmclk
                    nop
    
                    fltl      #PIN
                    wrpin     #(P_OE | P_PWM_SAWTOOTH), #PIN
                    wxpin     ##XREG, #PIN
                    wypin     duty, #PIN
                    drvl      #PIN
    
    loop            waitx     ##(CLK_FREQ / 50)
                    incmod    duty, #UNITS
                    wypin     duty, #PIN
                    jmp       #loop                
    
    duty            long      0
    
                    fit       496
    
Sign In or Register to comment.