P2 PASM PWM with NCO

in Propeller 2
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
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.
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
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?
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.
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