I have been playing with ways of using the Propeller to aid in handling SSB signal generation,
and in particular have come up with what seems to be a novel approach (which is well suited
to the Propeller, whose DSP capabilities are otherwise severely restricted by a lack of hardware
The basic idea is to sum the output of two identical DDS units with distinct phase-offsets to
generate an output of controllable amplitude and phase. (DDS = 'direct digital synthesis')
Normally a DDS unit outputs a fixed amplitude sinewave by table-lookup from a phase accumulator.
The phase accumulator is stepped on every cycle by an increment that represents the frequency
of the output wave (w.r.t. the DDS clock).
The Prop can run a DDS loop fairly tightly (> 1MHz rate) since only addition and table lookup
are needed (alas the ROM sine table is not suitable as its only a single quadrant). And the counters'
FRQx and PHSx registers can do some of the lifting.
But multiplying the output to 16 bit accuracy would slow things down to perhaps 250kHz at best.
This can be improved by using mutiple interleaved cogs, but cogs are a very finite resource.
However summing two values of equal amplitude and frequency but different phase gives
a result with arbitrary amplitude - running two DDS loops and one additional ADD is not much slower than
one DDS loop, and takes only one cog.
So my basic ASM loop is:
:topofloop mov off1, PHSA ' basic dual DDS loop, 16 instructions, all hub instructions aligned
mov off2, PHSB ' use the counters' NCO mode as our DDS accumulator
shr off1, #18 ' shift for the table (which has 2^13 word entries)
add off1, wave_table
rdword off1, off1 ' read the 16 bit sine value
shr off2, #18 ' do the second DDS too
add off2, wave_table
rdword off2, off2
add off1, off2 ' sum the DDS outputs, a 17 bit unsigned output value suitable for
mov OUTA, off1 ' R-2R DAC on pins 16:0 (although 12 or 14 bits is enough)
nop ' keep exactly 64 clocks per loop...
djnz n, #:innerloop ' loop for all but first 6 times which are unrolled to allow extra work
There's a lot of complication I'm not showing around updating the FRQx registers according to externally
provided (changing) phase angles - done using several unrolled copies of this loop and replacing the NOPs
and DJNZ with some tricky stuff.
Anyway the upshot is that I can generate (currently using a 9 bit R-2R resistor ladder), SSB at frequencies upto
about 500kHz from an audio signal source (currently sine or square wave).
My test harness uses a CORDIC cog to generate the signal, I then have a cog implementing a complex IIR
digital filter to produce band-limited quadrature audio signal from this.
The quadrature signals are passed to a cog that calculates the phase(z) (using atan2, again CORDIC), and arcsin(magnitude(z))
via log/antilog and arcsin lookup tables. This gives two angle values to drive the above DDS system.
Square wave test, LO = 87kHz
I'll post some more details soon.