CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long cogon, cog long sDutyA ' order important (the variables are read from memory in this order) long sDutyB ' order important (the variables are read from memory in this order) long sPinAOut1 long sPinAOut2 long sPinBOut1 long sPinBOut2 long sPeriod long sCtraVal long sCtrbVal PUB TESTEN Init(0,1,2,3) PUB Init(PinA1,PinA2,PinB1,PinB2) : okay 'start pwm on Pin @ 8 kHz 0..100,00% stop longfill(@sDutyA, 0, 9) sDutyA := 10000/3 sDutyB := 10000/2 sPinAOut1 := |< PinA1 sPinAOut2 := |< PinA2 sPinBOut1 := |< PinB1 sPinBOut2 := |< PinB2 ' sCtraVal := %00100 << 26 + PinA1 ' sCtrbVal := %00100 << 26 + PinB1 sCtraVal := %00101 << 26 + PinA1 + PINA2 << 9 sCtrbVal := %00101 << 26 + PinB1 + PINB2 << 9 sPeriod := 10000 okay := cogon := (cog := cognew(@entry,@sDutyA)) > 0 PUB stop '' Stop object - frees a cog if cogon~ cogstop(cog) longfill(@sDutyA, 0, 9) PUB SetPeriod(counts) ' set pwm period in clock cycles, frequency = (_clkfreq / period) sPeriod := counts PUB SetDutyA(counts) if (counts < 0) counts := 0 if (counts > 10000) counts := 10000 sDutyA :=counts PUB SetDutyB(counts) if (counts < 0) counts := 0 if (counts > 10000) counts := 10000 sDutyB :=counts DAT 'assembly cog which updates the PWM cycle on APIN 'for audio PWM, fundamental freq which must be out of auditory range (period < 50?S) org 0 entry mov T0,par 'get first parameter add T0,#8 rdlong tmp, T0 or dira, tmp ' set pinOut to output add T0,#4 rdlong tmp, T0 or dira, tmp ' set pinOut to output add T0,#4 rdlong tmp, T0 or dira, tmp ' set pinOut to output add T0,#4 rdlong tmp, T0 or dira, tmp ' set pinOut to output add T0, #4 rdlong period, T0 'sPeriod mov frqa, #1 'set counter to increment 1 each cycle mov frqb, #1 'set counter to increment 1 each cycle mov time, cnt 'record current time add time, period 'establish next period add T0, #4 rdlong tmp, T0 mov ctra, tmp 'sCtraVal add T0, #4 rdlong tmp, T0 mov ctrb, tmp 'sCtraVal mov T0,par 'get first parameter add T0, #4 :loop rdlong valueA, par 'get an up to date pulse width rdlong valueB, T0 'get an up to date pulse width waitcnt time, period 'wait until next period neg phsa, valueA 'back up phsa so that it trips "value" cycles from now neg phsb, valueB 'back up phsa so that it trips "value" cycles from now jmp #:loop 'loop for next cycle valueA res 1 valueB res 1 ctraval res 1 ctrbval res 1 period res 1 time res 1 T0 res 1 tmp res 1