On each step one winding goes high or one winding goes low, snaking around the 5 phases.
I'd recommend first tackling this as it will prove the rest of the hardware and is much easier to
get working in the first instance.
sinusoidal PWM involves synchonizing 5 PWM clocks and providing duty cycles of the form
50% + amplitude% * sin (phase)
The synchronization is required with a 5-wire motor as the windings cannot be independently
driven. The amplitude controls the strength of drive (there is no equivalent to this with trapezoidal
drive method).
Note that is amplitude is zero, all the PWM channels are at 50% duty cycle and exactly in phase.
The windings see no drive at all in this condition.
So on every PWM cycle you need to provide a new sin(phase) value to each PWM cog that are 72 degrees
apart. A DDS loop can dole out the values, using a sine lookup table (alas the ROM table is probably too slow
to use for 5 waveforms, a complete 360 degree table that's a power-of-two in size in RAM is the way
to go.
Scaling by the amplitude involves a multiply - that's best farmed out to the PWM cogs to share the
workload.
BTW in case its not obvious 5 phase PWM control is analogous to 3 phase control, you just replace 3 by 5 and 120 degree by 72 degree, so any 3-phase code can be adapted.
and there is also this useful chestnut
"This results in the 2-phase having 200 steps per rotation, 1.8° per step, while the 5-phase has 500 steps per rotation, 0.72° per step. The increased resolution of the 5-phase is inherent to its design. When coupled with a microstepping driver, the 5-phase motor can make steps as small as 0.00288°, however, position accuracy and repeatability are still subject to the motor's mechanical accuracy. The mechanical accuracy of both the 2-phase and 5-phase motor is ± 3 arc minutes (0.05°)."
that Mechanical limit, is Step/14.4, which explains why Microsteps above 32 are not really mentioned.
It does mean the 256 steps mentioned is outside the scope of these motors, but PhPi's nifty code can manage higher PWM kHz for reduced steps.
50% + amplitude% * sin (phase)
.........................................
A DDS loop can dole out the values, using a sine lookup table (alas the ROM table is probably too slow
to use for 5 waveforms, a complete 360 degree table that's a power-of-two in size in RAM is the way
to go.
Scaling by the amplitude involves a multiply - that's best farmed out to the PWM cogs to share the
workload.
"Sine wave" in the thread title got my attention because I have wondered what it would take to design a variable frequency drive for a three phase induction motor for a possible future project. This looks like good information. I get the sense that I'm going to have to learn about "DDS loops".
It is possible to use two single DDS devices that operate on the same master clock to output two signals whose phase relationship can then be directly controlled. In Figure 8, two AD9834s are programmed using one reference clock, with the same reset pin being used to update both parts. Using this setup, it is possible to do I-Q modulation.
Figure 8
Figure 8. Multiple DDS ICs in synchronous mode.
A reset must be asserted after power-up and prior to transferring any data to the DDS. This sets the DDS output to a known phase, which serves as the common reference point that allows synchronization of multiple DDS devices. When new data is sent simultaneously to multiple DDS units, a coherent phase relationship can be maintained, and their relative phase offset can be predictably shifted by means of the phase-offset register.
FWIW, here's a program that outputs analog sine waves 72° apart:
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
CLK_PIN = 6
PH0_PIN = 1
PH1_PIN = 2
PH2_PIN = 3
PH3_PIN = 4
PH4_PIN = 5
NO_PIN = $ff
PUB start
cognew(@wavegen, @group0)
cognew(@wavegen, @group1)
cognew(@wavegen, @group2)
waitcnt(cnt + clkfreq / 10)
dira[CLK_PIN]~~
frqa := $10000000
ctra := %00100 << 26 | CLK_PIN
repeat
DAT
group0 long CLK_PIN << 24 | PH0_PIN << 16 | PH1_PIN << 8 | 0
group1 long CLK_PIN << 24 | PH2_PIN << 16 | PH3_PIN << 8 | 100
group2 long CLK_PIN << 24 | PH4_PIN << 16 | NO_PIN << 8 | 200
org 0
wavegen rdlong phase0,par
mov clkpin,phase0
shr clkpin,#24
mov clkmask,#1
shl clkmask,clkpin
mov ph0pin,phase0
shr ph0pin,#16
and ph0pin,#$ff
mov ph1pin,phase0
shr ph1pin,#8
and ph1pin,#$ff
and phase0,#$ff
add phase0,#sine
mov phase1,phase0
add phase1,#50
cmp ph0pin,#NO_PIN wz
if_nz movs ctr0,ph0pin
if_nz mov ctra,ctr0
if_nz mov acc,#1
if_nz shl acc,ph0pin
if_nz mov dira,acc
cmp ph1pin,#NO_PIN wz
if_nz movs ctr0,ph1pin
if_nz mov ctrb,ctr0
if_nz mov acc,#1
if_nz shl acc,ph1pin
if_nz or dira,acc
main_lp movs loadfrqa,phase0
movs loadfrqb,phase1
add phase0,#1
cmp phase0,#sine+250 wz
if_z mov phase0,#sine
add phase1,#1
cmp phase1,#sine+250 wz
if_z mov phase1,#sine
waitpne clkmask,clkmask
waitpeq clkmask,clkmask
loadfrqa mov frqa,0-0
loadfrqb mov frqb,0-0
jmp #main_lp
ctr0 long %00110 << 26
sine long $7fffffff,$83377685,$866e67e4,$89a44f0c,$8cd8a718
long $900aeb61,$933a9798,$966727da,$999018c3,$9cb4e786
long $9fd51201,$a2f016d2,$a605756b,$a914ae2b,$ac1d426b
long $af1eb49b,$b2188850,$b50a425b,$b7f368dd,$bad38358
long $bdaa1ac6,$c076b9ab,$c338ec28,$c5f0400b,$c89c44e7
long $cb3c8c21,$cdd0a905,$d05830d6,$d2d2bae1,$d53fe08b
long $d79f3d64,$d9f06f39,$dc33161d,$de66d480,$e08b4f3b
long $e2a02d9e,$e4a5197f,$e699bf49,$e87dce08,$ea50f778
long $ec12f00d,$edc36f07,$ef622e77,$f0eeeb4c,$f2696561
long $f3d15f81,$f5269f79,$f668ee1c,$f798174a,$f8b3ea00
long $f9bc3858,$fab0d796,$fb91a02d,$fc5e6dc3,$fd171f3b
long $fdbb96b7,$fe4bb9a1,$fec770a8,$ff2ea7ce,$ff814e5f
long $ffbf5701,$ffe8b7aa,$fffd69ab,$fffd69aa,$ffe8b7a7
long $ffbf56fb,$ff814e57,$ff2ea7c2,$fec7709b,$fe4bb990
long $fdbb96a5,$fd171f26,$fc5e6dab,$fb91a013,$fab0d77a
long $f9bc3839,$f8b3e9de,$f7981726,$f668edf6,$f5269f51
long $f3d15f57,$f2696534,$f0eeeb1d,$ef622e46,$edc36ed4
long $ec12efd8,$ea50f740,$e87dcdcf,$e699bf0d,$e4a51941
long $e2a02d5e,$e08b4efa,$de66d43d,$dc3315d8,$d9f06ef2
long $d79f3d1c,$d53fe040,$d2d2ba95,$d0583088,$cdd0a8b5
long $cb3c8bd0,$c89c4495,$c5f03fb8,$c338ebd3,$c076b955
long $bdaa1a6f,$bad382ff,$b7f36883,$b50a4201,$b21887f5
long $af1eb43f,$ac1d420e,$a914adcc,$a605750c,$a2f01672
long $9fd511a0,$9cb4e725,$99901861,$96672777,$933a9735
long $900aeafe,$8cd8a6b4,$89a44ea9,$866e6781,$83377621
long $7fffff9b,$7cc88916,$799197b6,$765bb08e,$73275883
long $6ff5143b,$6cc56804,$6998d7c2,$666fe6da,$634b1817
long $602aed9d,$5d0fe8cd,$59fa8a34,$56eb5175,$53e2bd35
long $50e14b06,$4de77752,$4af5bd48,$480c96c8,$452c7c4e
long $4255e4e0,$3f8945fc,$3cc71381,$3a0fbf9f,$3763bac5
long $34c3738d,$322f56aa,$2fa7cedb,$2d2d44d2,$2ac01f29
long $2860c251,$260f907e,$23cce99c,$21992b3b,$1f74b082
long $1d5fd221,$1b5ae641,$19664079,$178231bc,$15af084f
long $13ed0fbb,$123c90c3,$109dd156,$0f111483,$0d969a71
long $0c2ea052,$0ad9605c,$099711bd,$0867e891,$074c15dd
long $0643c787,$054f284b,$046e5fb7,$03a19224,$02e8e0ae
long $02446934,$01b4464d,$01388f48,$00d15825,$007eb196
long $0040a8f7,$00174850,$00029652,$00029656,$0017485b
long $0040a909,$007eb1b0,$00d15847,$01388f71,$01b4467e
long $0244696c,$02e8e0ee,$03a1926a,$046e6005,$054f28a1
long $0643c7e4,$074c1641,$0867e8fb,$0997122e,$0ad960d5
long $0c2ea0d2,$0d969af7,$0f111510,$109dd1e9,$123c915d
long $13ed105c,$15af08f5,$17823269,$1966412c,$1b5ae6fa
long $1d5fd2df,$1f74b146,$21992c05,$23ccea6b,$260f9153
long $2860c32b,$2ac02008,$2d2d45b5,$2fa7cfc3,$322f5798
long $34c3747f,$3763bbbb,$3a0fc09a,$3cc71480,$3f8946ff
long $4255e5e6,$452c7d57,$480c97d4,$4af5be58,$4de77865
long $50e14c1c,$53e2be4e,$56eb5290,$59fa8b51,$5d0fe9ec
long $602aeebe,$634b193b,$666fe7ff,$6998d8e9,$6cc5692b
long $6ff51563,$732759ad,$765bb1b8,$799198e1,$7cc88a40
clkpin res 1
clkmask res 1
ph0pin res 1
acc res 1
ph1pin res 1
phase0 res 1
phase1 res 1
It uses three PASM cogs and their counters to produce five DUTY-mode outputs. Phase advancements are synchronized to an NCO clock output on P0. I filtered the outputs with an RC filter (1K, 220pF) to produce the following scope trace. (My scope has only four channels, so I couldn't show the fifth channel. But I did verify that it was there and correct.)
The unfiltered DUTY-mode output changes state way too fast to input to a PWM-style driver. But there are chips that convert analog voltages to a proper PWM signal. Alternatively, one could produce a sawtooth output on another pin and use that with comparators to produce the PWM'd signals.
The unfiltered DUTY-mode output changes state way to fast to input to a PWM-style driver. But there are chips that convert analog voltages to a proper PWM signal. Alternatively, one could produce a sawtooth output on another pin and use that with comparators to produce the PWM'd signals.
There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
Way back when.... When I was choosing steppers and drivers, I clearly saw that Oriental Motors was going in a proprietary direction.... So I ran the other way, and instead I chose the norm. I would hate to be in your shoes.
EDIT: Sell those motors and buy normal stepper motors, and you will be glad you did. Just my two cents.
There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
But not a 5-wire 5-phase motor surely, as the windings are not independent.
There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
But not a 5-wire 5-phase motor surely, as the windings are not independent.
Well, yes, clearly not from a single channel of Class-D
Sell those motors and buy normal stepper motors, and you will be glad you did. Just my two cents.
Despite the five-phase motors being more complicated to interface and program, I believe they do have an advantage when it comes to smooth running. Mercedes Benz recognized such an advantage when they came out with their 300D (a five-cylinder diesel) many years ago.
"Depending on your particular application, a 2-phase motor may suffice. However, 5-phase stepper motors offer higher resolution, lower vibration, higher acceleration and deceleration rates (due to smaller step angles), and are less likely to lose synchronization due to overshooting/undershooting than a 2-phase stepper motor. For applications requiring high precision, low noise and low vibration, 5-phase is the better technology."
... "Depending on your particular application, a 2-phase motor may suffice. However, 5-phase stepper motors offer higher resolution, lower vibration, higher acceleration and deceleration rates (due to smaller step angles), and are less likely to lose synchronization due to overshooting/undershooting than a 2-phase stepper motor. For applications requiring high precision, low noise and low vibration, 5-phase is the better technology."
All of that is true, until you bring micro-stepping to the table.
Of course, they rather skirt around that, with statements like this
"Vibration
Because of the smaller step angles in 5-phase stepper motors, 0.72° versus 1.8° in a 2-phase motor, the vibration in a 5-phase motor is much less than in a 2-phase."
And nothing was said in the article about resonance. Two-phase steppers can have terrible resonance characteristics (cogging and losing steps), unless they are physically damped and/or employ clever programming to minimize time spent in the resonance zone. (Maybe even dithering would work here?) I once had to incorporate a spring-loaded cork-and-metal drag mechanism (as in a fishing reel) to dampen out resonance in a stepper drive.
I do not know how five-phase motors' resonance characteristics compare.
And nothing was said in the article about resonance. Two-phase steppers can have terrible resonance characteristics (cogging and losing steps), unless they are physically damped and/or employ clever programming to minimize time spent in the resonance zone. (Maybe even dithering would work here?) I once had to incorporate a spring-loaded cork-and-metal drag mechanism (as in a fishing reel) to dampen out resonance in a stepper drive.
I do not know how five-phase motors' resonance characteristics compare.
I had to look up to see what "cogging" was.
In one of my stepper projects I dealt with the cogging problem by reducing the PWM duty cycle whenever the stepper was rotating slowly or during acceleration/deceleration. I inserted a PNP transistor into the power supply. (Low side NPN did not work.)
Question - why can't you just use 5 cogs and time it out to get the frequency you need?
Of course, that is possible.
Phil's code could have used one timer per COG, rather than the 2 timers each COGs already has, and consumed 5 COGs instead.
Despite the five-phase motors being more complicated to interface and program, I believe they do have an advantage when it comes to smooth running.
Perhaps this is true, but there are always pros and cons to every trade off. To me, simplicity, and readily available, inexpensive parts, are worth there weight in gold. As I have told you before, the best advice you ever gave me, was to purchase some of the readily available PWM stepper drivers. Prior to purchasing those drivers, I was going in circles and wasting a lot of time and money.
Perhaps this is true, but there are always pros and cons to every trade off. To me, simplicity, and readily available, inexpensive parts, are worth there weight in gold. As I have told you before, the best advice you ever gave me, was to purchase some of the readily available PWM stepper drivers. Prior to purchasing those drivers, I was going in circles and wasting a lot of time and money.
Absolutely agree: Phil Pilgrim's advice is worth its weight in gold.
I have a question.
In the code below, If "i" (is from 0 to 7), why in "duty" is it only shifted left 6 times not 7?
Thank you
________________________________________________________________________________________
From PWMx8.Demo.spin
PUB start | i, duty
' Program to demonstrate the pwm_x8 object.
pwm.start(base_pin, %1111_1111, 23000) 'Setup for PWM output on pins A16 - A23 at 23KHz.
repeat
repeat value from 0 to 511
repeat i from 0 to 7
duty := ((value + (i << 6)) & 511)
if duty > 255
duty := 511 - duty
pwm.duty(base_pin + i, duties[duty])
______________________________________________________________________________________________
I have been reading thru code/manuals/forum posts and application notes and I am crossed eyed now.
I am getting there but need a little help.
Code below. Questions in red.
Thank You
________________________________________________________________________________________________
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
CLK_PIN = 6
PH0_PIN = 1
PH1_PIN = 2---Pin assignments with base 10? Should be binary right?
PH2_PIN = 3
PH3_PIN = 4
PH4_PIN = 5
NO_PIN = $ff
PUB start
cognew(@wavegen, @group0)
cognew(@wavegen, @group1)
cognew(@wavegen, @group2)
waitcnt(cnt + clkfreq / 10)
dira[CLK_PIN]~~
frqa := $10000000
ctra := %00100 << 26 | CLK_PIN----Is this OR'ng 26 and clk_pin
repeat or binary number shifted left 26 times then OR'ed with a base 10 number?
DAT
group0 long CLK_PIN << 24 | PH0_PIN << 16 | PH1_PIN << 8 | 0
group1 long CLK_PIN << 24 | PH2_PIN << 16 | PH3_PIN << 8 | 100---What it this?
group2 long CLK_PIN << 24 | PH4_PIN << 16 | NO_PIN << 8 | 200---What is going on here?
org 0
wavegen rdlong phase0,par
mov clkpin,phase0
shr clkpin,#24--\
mov clkmask,#1----\Why shr/mov/shl when it was done above?
shl clkmask,clkpin--/
mov ph0pin,phase0
shr ph0pin,#16
and ph0pin,#$ff
mov ph1pin,phase0
shr ph1pin,#8
and ph1pin,#$ff
and phase0,#$ff
add phase0,#sine
mov phase1,phase0
add phase1,#50
shift binds more tightly than or, its generating bit fields by oring them together, and individual fields
by shifting them left. Basically most of this code is packing several fields into one long.
The thing with sine is a table in cog ram, whose first entry has the label sine. The code is traversing
phase0 & phase1 from sine to sine+250, ie phaseX are register numbers (used by the MOVS instructions
to modify the instructions that set FRQA and FRQB)
Comments
Right, that requires all the outputs to be in step, basically one DDS generated signal controls all the pins.
As background the standard trapezoidal step pattern is something like: On each step one winding goes high or one winding goes low, snaking around the 5 phases.
I'd recommend first tackling this as it will prove the rest of the hardware and is much easier to
get working in the first instance.
sinusoidal PWM involves synchonizing 5 PWM clocks and providing duty cycles of the form
50% + amplitude% * sin (phase)
The synchronization is required with a 5-wire motor as the windings cannot be independently
driven. The amplitude controls the strength of drive (there is no equivalent to this with trapezoidal
drive method).
Note that is amplitude is zero, all the PWM channels are at 50% duty cycle and exactly in phase.
The windings see no drive at all in this condition.
So on every PWM cycle you need to provide a new sin(phase) value to each PWM cog that are 72 degrees
apart. A DDS loop can dole out the values, using a sine lookup table (alas the ROM table is probably too slow
to use for 5 waveforms, a complete 360 degree table that's a power-of-two in size in RAM is the way
to go.
Scaling by the amplitude involves a multiply - that's best farmed out to the PWM cogs to share the
workload.
The Oriental Motor docs have a slight variant on that, with a 3-on-7 off step mapping, which looks to always have 3 driving.
and there is also this useful chestnut
"This results in the 2-phase having 200 steps per rotation, 1.8° per step, while the 5-phase has 500 steps per rotation, 0.72° per step. The increased resolution of the 5-phase is inherent to its design. When coupled with a microstepping driver, the 5-phase motor can make steps as small as 0.00288°, however, position accuracy and repeatability are still subject to the motor's mechanical accuracy. The mechanical accuracy of both the 2-phase and 5-phase motor is ± 3 arc minutes (0.05°)."
that Mechanical limit, is Step/14.4, which explains why Microsteps above 32 are not really mentioned.
It does mean the 256 steps mentioned is outside the scope of these motors, but PhPi's nifty code can manage higher PWM kHz for reduced steps.
https://www.analog.com/en/analog-dialogue/articles/all-about-direct-digital-synthesis.html
It is possible to use two single DDS devices that operate on the same master clock to output two signals whose phase relationship can then be directly controlled. In Figure 8, two AD9834s are programmed using one reference clock, with the same reset pin being used to update both parts. Using this setup, it is possible to do I-Q modulation.
Figure 8
Figure 8. Multiple DDS ICs in synchronous mode.
A reset must be asserted after power-up and prior to transferring any data to the DDS. This sets the DDS output to a known phase, which serves as the common reference point that allows synchronization of multiple DDS devices. When new data is sent simultaneously to multiple DDS units, a coherent phase relationship can be maintained, and their relative phase offset can be predictably shifted by means of the phase-offset register.
It uses three PASM cogs and their counters to produce five DUTY-mode outputs. Phase advancements are synchronized to an NCO clock output on P0. I filtered the outputs with an RC filter (1K, 220pF) to produce the following scope trace. (My scope has only four channels, so I couldn't show the fifth channel. But I did verify that it was there and correct.)
The unfiltered DUTY-mode output changes state way too fast to input to a PWM-style driver. But there are chips that convert analog voltages to a proper PWM signal. Alternatively, one could produce a sawtooth output on another pin and use that with comparators to produce the PWM'd signals.
-Phil
Very nifty.
There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
-Phil
EDIT: Sell those motors and buy normal stepper motors, and you will be glad you did. Just my two cents.
Well, yes, clearly not from a single channel of Class-D
From this article:
"Depending on your particular application, a 2-phase motor may suffice. However, 5-phase stepper motors offer higher resolution, lower vibration, higher acceleration and deceleration rates (due to smaller step angles), and are less likely to lose synchronization due to overshooting/undershooting than a 2-phase stepper motor. For applications requiring high precision, low noise and low vibration, 5-phase is the better technology."
-Phil
All of that is true, until you bring micro-stepping to the table.
Of course, they rather skirt around that, with statements like this
"Vibration
Because of the smaller step angles in 5-phase stepper motors, 0.72° versus 1.8° in a 2-phase motor, the vibration in a 5-phase motor is much less than in a 2-phase."
I do not know how five-phase motors' resonance characteristics compare.
-Phil
Resonance also improves with microstepping. Some nice plots here : https://www.trinamic.com/technology/std-technologies/microstepping/
In one of my stepper projects I dealt with the cogging problem by reducing the PWM duty cycle whenever the stepper was rotating slowly or during acceleration/deceleration. I inserted a PNP transistor into the power supply. (Low side NPN did not work.)
Of course, that is possible.
Phil's code could have used one timer per COG, rather than the 2 timers each COGs already has, and consumed 5 COGs instead.
Perhaps this is true, but there are always pros and cons to every trade off. To me, simplicity, and readily available, inexpensive parts, are worth there weight in gold. As I have told you before, the best advice you ever gave me, was to purchase some of the readily available PWM stepper drivers. Prior to purchasing those drivers, I was going in circles and wasting a lot of time and money.
I have a question.
In the code below, If "i" (is from 0 to 7), why in "duty" is it only shifted left 6 times not 7?
Thank you
________________________________________________________________________________________
From PWMx8.Demo.spin
PUB start | i, duty
' Program to demonstrate the pwm_x8 object.
pwm.start(base_pin, %1111_1111, 23000) 'Setup for PWM output on pins A16 - A23 at 23KHz.
repeat
repeat value from 0 to 511
repeat i from 0 to 7
duty := ((value + (i << 6)) & 511)
if duty > 255
duty := 511 - duty
pwm.duty(base_pin + i, duties[duty])
______________________________________________________________________________________________
I am getting there but need a little help.
Code below. Questions in red.
Thank You
________________________________________________________________________________________________
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
CLK_PIN = 6
PH0_PIN = 1
PH1_PIN = 2---Pin assignments with base 10? Should be binary right?
PH2_PIN = 3
PH3_PIN = 4
PH4_PIN = 5
NO_PIN = $ff
PUB start
cognew(@wavegen, @group0)
cognew(@wavegen, @group1)
cognew(@wavegen, @group2)
waitcnt(cnt + clkfreq / 10)
dira[CLK_PIN]~~
frqa := $10000000
ctra := %00100 << 26 | CLK_PIN----Is this OR'ng 26 and clk_pin
repeat or binary number shifted left 26 times then OR'ed
with a base 10 number?
DAT
group0 long CLK_PIN << 24 | PH0_PIN << 16 | PH1_PIN << 8 | 0
group1 long CLK_PIN << 24 | PH2_PIN << 16 | PH3_PIN << 8 | 100---What it this?
group2 long CLK_PIN << 24 | PH4_PIN << 16 | NO_PIN << 8 | 200---What is going on here?
org 0
wavegen rdlong phase0,par
mov clkpin,phase0
shr clkpin,#24--\
mov clkmask,#1----\Why shr/mov/shl when it was done above?
shl clkmask,clkpin--/
mov ph0pin,phase0
shr ph0pin,#16
and ph0pin,#$ff
mov ph1pin,phase0
shr ph1pin,#8
and ph1pin,#$ff
and phase0,#$ff
add phase0,#sine
mov phase1,phase0
add phase1,#50
cmp ph0pin,#NO_PIN wz
if_nz movs ctr0,ph0pin
if_nz mov ctra,ctr0
if_nz mov acc,#1
if_nz shl acc,ph0pin
if_nz mov dira,acc
cmp ph1pin,#NO_PIN wz
if_nz movs ctr0,ph1pin
if_nz mov ctrb,ctr0
if_nz mov acc,#1
if_nz shl acc,ph1pin
if_nz or dira,acc
main_lp movs loadfrqa,phase0
movs loadfrqb,phase1
add phase0,#1
cmp phase0,#sine+250 wz---Why add 250 to sine?
if_z mov phase0,#sine
add phase1,#1
cmp phase1,#sine+250 wz
if_z mov phase1,#sine
waitpne clkmask,clkmask
waitpeq clkmask,clkmask
loadfrqa mov frqa,0-0
loadfrqb mov frqb,0-0
jmp #main_lp
________________________________________________________________________________________________
-Phil
by shifting them left. Basically most of this code is packing several fields into one long.
The thing with sine is a table in cog ram, whose first entry has the label sine. The code is traversing
phase0 & phase1 from sine to sine+250, ie phaseX are register numbers (used by the MOVS instructions
to modify the instructions that set FRQA and FRQB)