Close

Synthesis and Modulation

A project log for Careless WSPR

A desultorily executed Weak Signal Propagation Reporter beacon.

ziggurat29ziggurat29 08/21/2019 at 16:520 Comments

Summary

Finally, it is time to fiddle with the Si5351A (the original motivation for this project; lol).  I look at some libraries and wind up more or less winging it.

Deets

Now that all the pieces are in place and presumably working, it's finally time to make the synthesizer chip do its thing.  The Si5351 is conceptually simple:

The goal is to create program the PLL to generate some high frequency from the input clock source, and then use the 'MultiSynth' to divided it down to your desired output frequency.  This scheme can support output from 2.5 KHz to 200 MHz.  There is one MultiSynth per output, so that is conceptually straightforward, but the MultiSynths can be connected to either of two PLLs.  Since there is not one PLL per output, different outputs will need to share PLLs, so you have to do a little planning to figure out what that common PLL should be producing in order to satisfy all the MultiSynths to which it is connected.

If you're not familiar with a PLL, it's a control system wherein the goal is to maintain zero phase difference between two inputs.  The output is proportional to the phase difference (and subject to various internal filtering to get the response as desired).  That output is typically fed into a variable frequency oscillator that serves as one of those inputs, and in this way the oscillator's frequency is made to track the input frequency (and moreover be in-phase).  This sounds kind of boring in itself, but it gets interesting when you put frequency dividers in the loop.  By dividing the variable frequency oscillator by some factor, say 'M' before putting it into the the input, then that oscillator will need to be made to operate at M times the external input frequency.  This is how you can 'synthesize' various frequencies from a single input frequency.  You can put dividers at various other points in the system as well to provide more options.  It's very much like designing an amplifier with an op-amp:  there you use voltage dividers and a differential amplifier to be able to generate the desired voltage transformation, and here you use frequency dividers and a phase detector to be able to generate the desired frequency transformation.

This device has 188 registers that have to be programed to make it produce useful output.  That's an exaggeration because many of those registers are repeated (for the various multisynths), and this part only has three outputs -- not eight -- so the set is smaller than that absolute maximum.  But it is still quite bewildering coming from your core goal of 'I would like to produce frequency X on output Y'.  There is no frequency register per se.

But when you consider that this part was created "for replacing crystals, crystal oscillators, VCXOs, phase-locked loops (PLLs), and fanout buffers in cost-sensitive applications", then the design is a little more understandable.  The intended use-case involves using a separate desktop tool as a 'wizard' to grind through all the possibilities and come up with a solution comprising a list of registers and the value to which they should be set.  You then simply blindly program those values into the chip (and you can burn them into OTP memory so that the chip will come up in that configuration).  If you're using the chip as a replacement for multiple crystals in an integrated system, then this is plausible.  But we're using it in a way perhaps not as intended and need to alter the output frequencies on a frequent basis at runtime.

As a quicky, I did pre-compute the four FSK tones for the 20 m band and added routines to set the output to those values.  This was more for just seeing some output from the board, and to produce a fallback position if I couldn't figure out how to configure the device programatically.  It's not a desirable solution because then the project would be limited to using only a few output frequencies.  The output looked fine, incidentally, though of course I could not really tell the difference of 1.64 Hz on the oscilloscope when the center frequency is at 14,097,100 Hz.

OK, so now it was time to try that programatically.  I did some research, and there is what looks to be a good and comprehensive Si5351 library for the Arduino, ironically named 'Si5351Arduino':
https://github.com/etherkit/Si5351Arduino.git
but it is GPL and I have an allergy to that license.  In fact, I did not find a commercial-friendly licensed (e.g. BSD, etc) libraries, so I was going to be on my own.

The horse's mouth is an application note 'AN619 - Manually Generating an Si5351 Register Map' which explains the process in detail.  I did also find some sample code by Hans Summers that was useful in avoiding the grind of taking sets of multipliers, numerators, denominators, and packing them into register form.

In the end I punted in favor of moving the project forward, and only implemented a to-purpose device interface.  I would have preferred to make a more general-purpose support library, but that seems to be a mini-project in itself, so I will perhaps come back to that later if I need to.  The interface here assumes CLK0 output using PLLA, and simply takes a frequency parameter.  What is lost is supporting PLLB, configuring output MultiSynths to source from A or B, and to decompose the configuration between PLL and MultiSynth so that you can build arbitrary output plans.  I'll save that for later -- e.g. if I do the receive side of WSPR, I might want another output to be my LO to drive a mixer to downconvert the signal (and if I first convert to an IF, I might also need the remaining output to further downconvert to the baseband).

The simplified API wound up being:

int si5351aIsPresent ( void );
uint8_t si5351aStatus ( void );
void si5351aOutputOff(uint8_t clk);
void si5351aSetFrequency(uint64_t freqCentiHz);

The frequency is expressed in 64-bit centihertz as a fixed point representation instead of using 32-bit float (which only has 24 bits of precision, anyway).  The final results for the registers will be integers, anyway.

This was tested and /believed/ to be working -- I don't have test equipment on-hand to see if the output signal is actually being produced with sufficient frequency resolution that valid modulated WSPR is being produced.  Rather than trying to cruft together a test jig that /can/ prove it, I decided as a quicky to just try to decode my signal with the WSJT-X software from the author of the mode.

Next

Acid Test of the modulated signal

Discussions