Thursday, May 8, 2014

Finding Si570 divisors

Here is my function for determining an appropriate set of divisors (HSDiv and N1) given the desired output frequency that keeps the Si570 DCO within it's 4.85 GHz to 5.67 GHz operating range.

#define eSuccess 0
#define eFail 1
#define fDCOMinkHz 4850000 // Minimum DCO frequency in kHz
#define fDCOMaxkHz 5670000 // Maximum DCO frequency in kHz

int findDivisors(uint32_t fout, uint16_t &hsdiv, uint16_t &n1)
{
  const uint16_t HS_DIV[] = {11, 9, 7, 6, 5, 4};
  int32_t fout_kHz = fout / 1000;

  // Floor of the division
  uint16_t maxDivider = fDCOMaxkHz / fout_kHz;

  // Ceiling of the division
  n1 = 1 + ((fDCOMinkHz - 1) / fout_kHz / 11);

  if (n1 < 1 || n1 > 128)
    return eFail;

  while (n1 <= 128)
  {
    if (0 == n1 % 2 || 1 == n1)
    {
      // Try each divisor from largest to smallest order
      // to minimize power
      for (int i = 0; i < 6 ; ++i)
      {
        hsdiv = HS_DIV[i];
        if (hsdiv * n1 <= maxDivider)
          return eSuccess;
      }
    }
    n1++;
  }
  return eFail;
}

Plugging in my reset frequency of 56320000 we correctly calculate HSDiv of 11 and N1 of 8.  Spot checking other fOut values with the results from SiLabs tools so far checks out.  I will create a comprehensive test for this later, but pressing on...

So, considering the following test code:

uint32_t fOut = 56320000;  // My Si570 reset frequency
uint32_t fxtal = 114252366;
uint16_t HSDiv;
uint16_t N1;
uint64_t RFREQ;

if (findDivisors(fOut, HSDiv, N1) == eSuccess)
{
  uint64_t tmp = (uint64_t) fOut * HSDiv * N1;
  tmp = (tmp << 28) / (uint64_t) fxtal;
  RFREQ = tmp + ((tmp & 1<<(28-1))<<1); // Round result
}

So, with the input parameters specified, the RFREQ value I calculate is 0x2B6109F04 as compared to the reset value of 0x2B6109F08 which is within 0.00000001490116119384765625 of the reset value.  This amounts to an output frequency of 56.31999998 instead of 56.32 which is within 0.02 Hz.  I don't think I will worry about it.

As always, comments welcome.  Straighten me out if I am not thinking clearly about this.

Si570 math using integer math

So, if I have learned nothing else, it is that I am no mathematician and am really slow at figuring out this stuff.  Here is where I am at with regard to using integer math instead of floating point math for calculating the Si570 frequency setting elements.

Consider the following code segment:

uint32_t fxtal;
uint32_t fOut = 56320000; // My Si570 reset frequency
uint64_t RFREQ = 0x2B6109f08; // My Si570 RFREQ after reset
uint16_t HSDiv = 11; // My Si570 HSDiv after reset
uint16_t N1 = 8; // My Si570 N1 after reset
uint64_t tmp;

// Calculate fXtal for my device
fxtal = (((uint64_t) fOut * HSDiv * N1) << 28) / RFREQ;

// Calculate fOut value
tmp = ((uint64_t) fxtal * RFREQ / (uint64_t) (HSDiv * N1));
tmp = tmp + ((tmp & 1<<(28-1))<<1); // Round result
fOut = tmp >> 28;

Ok, so that is a bunch of math weirdness...  Let me try to illustrate a bit what I am doing.

The fxtal and fout values are 32 bit integers.  RFREQ on the other hand is a 38 bit fractional value with 10 bits of integer and 28 bits of fraction stored in a 64 bit unsigned integer.

So, promoting fOut to 64 bits before multiplication and then shifting left by 28 bits will align the decimal point between this partial result and the implied decimal point in RFREQ.  The division by RFREQ results in a 32 bit value with zero fractional bits.  In the case of the code above, I get the value 114252365 Hz.  I should probably round this result, but let's leave it as is for the moment.

Now that I know the crystal frequency, I should be able reverse the calculation to obtain the same fOut that I started with.  Remember that fOut = fxtal * RFREQ / (HSDiv * N1).

fOut is a 32 bit unsigned integer with zero fractional bits.  The formula contains an element (RFREQ) that has 28 fractional bits and 10 integer bits stored in a 64 bit integer type.  Basically it is the number 11644477192 / 2^28 which is 43.3790579140186309814453125 out to more fractional digits than I can handle (or need).

So, to handle this multiplication I use the integer value representation of RFREQ as a fixed point number with an implied decimal point between the 28th and 29th bits.  Multiplying RFREQ by fxtal which is a 32 bit integer, gives me a result that is 42 bits of integer (32+10) and 28 bits of fraction (28+0).  The result size (in bits) is the sum of the number of bits in the fractional part of each number plus the sum of the number of bits in the integer part.  Even though the result is 70 bits total (42+28), the upper 6 bits are unused, so the truncation to fit in a 64 bit unsigned integer results in no data loss.

Rounding the result is recommended, so we isolate at the most significant fractional bit and add it to the integer part.  Now, we have fOut scaled by 2^28.  Shifting right by 28 bits gives us the integer result we started with of 56320000.

Ok, now to calculate RFREQ, HSDiv and N1 given a desired fOut in the next posting.

More to come...

Tuesday, May 6, 2014

Si570 Programming continued...

While I certainly didn't intend to write a novel on the topic of Si570 programming, it is a topic that at least for me is unclear from datasheet.  What follows are my current findings.

Silicon Labs puts out an application program that will calculate the various settings for the chip given a desired frequency.  It will also calculate a new frequency and the associated settings based on a ppm change.


What becomes apparent from this tool is that Silicon Labs considers the 3500 ppm frequency change to be based on the output frequency rather than the DCO frequency.  My interpretation of the datasheet therefore has been incorrect as I had concluded that the 3500 ppm frequency excursion limit was calculated based on the DCO frequency.

Based on this, the following table shows the amount of frequency excursion that can be done taking into account the Minima transceiver IF frequency of 19.997000 Mhz.

   Band   + IF      3500 ppm (kHz)
    1.8    21.797    76.2895
    3.5    23.497    82.2395
    5       24.997    87.4895
    7       26.997    94.4895
   14      33.997  118.9895
   18      37.997  132.9895
   21      40.997  143.4895
   24      43.997  153.9895
   28      47.997  167.9895
   29      48.997  171.4895
   30      49.997  174.9895
   50      69.997  244.9895


I have also worked up a spreadsheet that illustrates the amount of change in RFREQ for a given output frequency increment of 0.01, 0.1, 1, 10, etc Hz.

   fOut (MHz)      fOut          RFREQ
                change (Hz)      change

    14.00000000           0           0
    14.00000001        0.01           9
    14.00000010         0.1          82   
    14.00000100           1         818   
    14.00001000          10        8177   
    14.00010000         100       81763   
    14.00100000        1000      817625   
    14.01000000       10000     8176246   
    14.10000000      100000    81762455   
    15.00000000     1000000   817624545


 
Based on this, it should be possible at these operating frequencies to set the frequency to within .01 Hz for ham bands up through and including the 6 metre band.

You would not however be able to keep the same divisors over more than the 3500 ppm range specified for the band of interest, contrary to my table above. 

More to come...

Saturday, May 3, 2014

Si570 Programming - Random Thoughts

In thinking about alternative methods of calculating the necessary parameters for the Si570 frequency setting elements, other than double precision floating point math, I have considered a number of approaches.

  • Fixed point math
  • Table lookup
The application of fixed point math is certainly a viable approach and one that I plan to complete an implementation of for purposes of comparison of strengths and weaknesses.  I wondered however about the need for such an approach when I consider a number of characteristics of the Si570.
  • There is a fair amount of frequency excursion that is possible without changing the values of N1 and HSDiv.
  • For any given pair of N1 and HSDiv, there is a minimum and maximum frequency that can be represented.
  • For a desired frequency increment within the minimum and maximum range of the N1 and HSDiv values currently set, there is a value that must be added to the current RFREQ value to change the frequency by that increment.
One could envision an approach where a table of output frequency ranges is stored consisting of an RFREQ, N1 and HSDiv value for the start of the range.  For the set of frequency increments desired (1Hz, 10Hz, 100Hz, 1kHz, etc) a RFREQ increment could be calculated in advance and stored with the rest of the table entries.

The frequency setting calculation for Si570 as we know is:

  fOut = fXtal * RFREQ / (N1 * HSDiv)

A change of frequency without changing N1 or HSDiv might be represented as follows:

  fOutNew = fXtal * (RFREQ + delta) / (N1 * HSDiv)

In practice, it might be tempting to calculate a single value for the smallest frequency change we wish to be able to apply and then just multiply that value by the number of increments of that amount we wish to make.  For example, if we decide the smallest frequency increment is 1Hz and calculate a value for delta necessary to move the output frequency by 1Hz, then to move 10Hz, we would just multiply the value by 10 and add it to RFREQ.  I think there is some danger in this approach that may or may not be sufficiently significant, depending on the application.

Any errors involved in the calculation of the stored values for RFREQ and delta will tend to accumulate.  These errors may in fact be very small, but it should be considered.  Calculating the values for several frequency increments in advance and always using the largest increment first where possible may help to minimize such errors at the expense of a little more table space.

It may also be desirable to store more than one value for RFREQ depending on the amount of error between the bottom and top of the range represented by the values of N1 and HSDiv.  Perhaps storing a value for the middle of the range rather than either end of the range or maybe storing a value for the top and bottom of the range.  The amount of error accumulation will need be analyzed and an appropriate scheme chosen to meet the accuracy needs of the application.

I believe it should be possible with a couple dozen table entries to represent the entire range of the CMOS version (10-160 MHz) with this approach with sufficient frequency setting resolution to implement a general purpose VFO or general coverage receiver.

Another item to consider for any table driven approach is how to calibrate the values stored.  An overall calibration value is unlikely to be applicable across the entire Si570 frequency range.  It may be that calibration values will need be determined and stored for each pair of N1 and HSDiv.

More to come...


Monday, April 21, 2014

Si570 Programming continued...

As previously mentioned, I held two possible interpretations of the datasheet regarding what is meant by how far the DCO frequency could be moved without restarting it.  My initial belief was that as long as no single change was more than 3500 ppm plus or minus that you could move it over the entire DCO range.  This turns out to be false.  You re-establish what the datasheet calls the "centre frequency" when you recalculate the RFREQ, HSDIV and N1 values and set them to the device.  A closer examination of the datasheet revealed the following:

As shown in Figure 3, the device allows reprogramming
of the DCO frequency up to ±3500 ppm from the center
frequency configuration without interruption to the
output clock. Changes greater than the ±3500 ppm
window will cause the device to recalibrate its internal
tuning circuitry, forcing the output clock to momentarily
stop and start at any arbitrary point during a clock cycle.
This re-calibration process establishes a new center
frequency and can take up to 10 ms. Circuitry receiving
a clock from the Si57x device that is sensitive to glitches
or runt pulses may have to be reset once the
recalibration process is complete.

So, it is in fact this recalibration process that establishes the new centre frequency.  This has been verified by experimentation.

From this I conclude there is a small frequency change procedure and a large frequency change procedure.  If the DCO frequency is changed no more than +/- 3500 ppm from the last centre frequency the a simple ratio multiplier is applied according to the following formulae:



Once a new RFREQ value (38 bits) is calculated, it is written to the Si570 device.  Since several registers must be rewritten, even with tiny changes in the RFREQ value these changes can affect the DCO frequency while the set of registers are being updated.  The Si570 provides a bit (register 135 bit 5) that can prevent this behaviour.  Setting this bit to 1 before changing the RFREQ registers and then resetting it will allow the output frequency to change in a single phase continuous step to the new frequency.

When changing the DCO frequency by more than +/- 3500 ppm, several steps are involved. Firstly, new values must be calculated for the HSDIV and N1 divisors.  Given the new desired output frequency, you must find the frequency divider values that will keep the DCO oscillation frequency in the range of 4.85 to 5.67 GHz.

To help minimize the device's power consumption, the divider values should be selected to keep the DCO's oscillation frequency as low as possible. The lowest value of N1 with the highest value of HS_DIV also results in the best power savings.  Since there are many solutions for a given output frequency, it is useful for power sensitive applications to pay attention to these details.

Once the divisors have been calculated, a new RFREQ value is determined according to the following formulae:


The new values are written to the device as follows:
  1. Freeze the DCO by setting bit 4 of Register 137
  2. Write the new frequency configuration by setting RFREQ, HSDIV and N1 new values to the appropriate registers.
  3. Unfreeze the DCO and assert the NewFreq bit without exceeding the timeout specified in Table 11 of the Si570 datasheet. (Register 135, bit 6).
The DCO output clock will momentarily stop and start at a completely arbitrary point in the clock cycle and can take up to 10 ms to complete with the expected assortment of glitches and runt pulses such behaviour would indicate.  If your downstream circuitry is sensitive to this nonsense, you may need to provide a reset mechanism to recover.

I find that the output waveform is basically a square wave signal.  On my device at least there is a bit of overshoot on the square wave signal both positive and negative at least at lower frequencies.  As I go higher in frequency, the waveform becomes more triangular in shape.  I will post oscilloscope traces of this behaviour later as my scope is a bit tied up right at the moment with another project.

More to come...

Sunday, April 20, 2014

Si570 Programming Continued...

The relationship between the various frequency setting elements is described as follows:

As previously mentioned, the output frequency is the result of the DCO frequency divided by the product of two divisors.  The DCO frequency is the product of a crystal frequency in the 114.25 MHz range and a settable reference frequency and must remain within the range of 4.85 to 5.67 Ghz.  RFREQ has 38 bits of resolution allowing for a theoretical frequency setting resolution of 0.09 ppb at the test frequency of 114.285 MHz.

The HSDIV and N1 values have additional restrictions on them, specifically HSDIV can have the values 4, 5, 6, 7, 9 or 11.  N1 can be 1 or any even number up to 128 inclusive (1, 2, 4, 6, ... 128).

Typically at startup you would determine the fxtal value specifically for your chip:
By interrogating the chip, one can determine the values for HSDIV, N1 and RFREQ.  By knowing the default startup frequency, the crystal frequency can be calculated.  In my case, HSDIV = 11, N1 = 8 and RFREQ is 0x2B6109f08.  Dividing this value by 2^28 gives me 0x2b as the integer portion or 43 decimal.  To figure out the fractional part one would divide 0x6109f08 (the least significant 28 bits of RFREQ) by 2^28.  Working in decimal instead of hex:

  0x6109f08 = 101752584 / 2^28 = 0.3790579140

Adding this to the integer portion gives me a RFREQ value of 43.3790579140.  Plugging this and the other knowns into the formula above gives me:

  fxtal = (56320000 * 11 * 8) / 43.3790579140 = 114252365.964832 or 114.252365 Mhz

The datasheet states that the crystal frequency is only accurate to +/- 2000 ppm at 114.285 Mhz, or about +/- 0.22857 so my device is within the pretty horrible specification.

So, running this the other way, the output frequency is found as:

  fout = (114252365 * 43.3790579140) / 11 * 8 = 56319999.524391 = 56.32 Mhz

A guy could envision a mechanism wherein you output a WWV frequency and tweak RFREQ until zero beat and then store the value for future reference, but the known frequency technique will get you very close.

If the DCO frequency is only moved +/- 3500 ppm, the oscillator output will be phase continuous.  This should make implementing protocols such as WSPR, JT65 and the like much cleaner than my previous work using the Parallax Propeller.  Also, in theory there is .42 Hz frequency resolution capable which would allow for much closer FSK tone shifts used in WSPR than the 1Hz resolution I had with the propeller.

It is unclear from the datasheet what is precisely meant by the +/- 3500 ppm figure.  One interpretation is that once you have moved a total of 3500 ppm from whatever frequency you last set using the "large frequency change technique", you would have to recalculate the RFREQ and divisor values and set them back to the device.  In my experience, most of the Arduino implementations I have reviewed have taken a flavor of this approach.  While this is certainly safe, it is unlikely to be necessary.  The other interpretation I have of the datasheet is that you could move the DCO over its entire range without recalculating parameters and do it in a phase continuous manner as long as no single frequency change is more than 3500 ppm.  My interpretation is that once you have changed the frequency by either of these mechanisms, the new DCO frequency (not the output frequency) becomes the new "center frequency" described in the datasheet.  So, under my theory, you could move the output frequency a total of 5.67 - 4.85 GHz = 0.82 Ghz 3500 ppm at a time.  Of course, this would require a different part than I have which only has a range of 10-160 Mhz.  Under this theory, as long as you didn't jump more than 17.5 Mhz between frequency settings, you only have to recalculate RFREQ and the change in frequency could be done phase continuous.  This theory I have not yet tested.

More to come...

Saturday, April 19, 2014

Si570 Programming

Messing around with the Si570 chip that is used in the Minima transceiver designed by Farhan Akhtar.  This is my lash-up:


After a bit of tweaking, I have the oscillator working.  It is no picnic trying to interpret the Si570 datasheet however.

Interestingly enough most of the code implementations I have looked at for the Arduino make a couple of errors in interpretation of the datasheet.  The Si570 is not really fun to program, but it has a number of benefits going for it.

My particular chip is a 10-160 MHz CMOS model.  When I first power it up, it comes up at 56.320 MHz.  The datasheet is not explicit on this, but supposedly the individual parts are "tuned" at the factory to their default frequency by adjusting the various parameters that are used to set the frequency.  However, the datasheet does not provide very flattering stability numbers and nowhere does it provide a statement of how closely it is calibrated in the factory.

So, in the absence of highly accurate frequency measurement capabilities you are faced with having to calculate the internal crystal frequency based on the default output frequency (from the datasheet) after reading the frequency setting parameters from the chip itself.

The Si570 requires mathematical calculations with 38 bits of precision in order to accurately set it's frequency.  Most Arduino implementations rely on double precision floating point math functionality.  However, the Arduino implementation of double precision is in fact identical to its single precision floating point.  Namely double = float data types silently behind the scenes.  So, most of these implementations give up on the number of digits of precision required to control the Si570 even down to the 1 Hz level.  Theoretically you should be able to set the frequency to within .42 Hz, but the unfortunate floating point double precision implementation on Arduino prevents even 1 Hz resolution.

The Si570 stores a reference frequency used in the output frequency calculation as a 38 bit values where 10 bits are use as a decimal multiplier.  The remaining 28 bits are a fractional multiplier stored as an integer value scaled by 2^28.

The internal DCO is constrained to 4.85 to 5.67 GHz determined by the internal crystal frequency multiplied by a reference frequency.  According to the settings in my chip, I calculate my crystal frequency to be 114.252365 MHz.  Secondarily, frequency excursions of the DCO can be done in a phase continuous manner if the change in frequency is no more than +/- 3500 PPM.  Many implementations however are calculating this based on the output frequency rather than the DCO frequency in error.  Frequency excursions larger than this require the DCO to be stopped and restarted in a non-phase continuous manner that can take upwards of 10 ms to complete.  Circuitry sensitive to runt pulses may require resetting after this operation.

The output frequency is the DCO frequency divided by the product of two divisors.  There are additional restrictions on these two divisors.

More to follow...




Monday, March 10, 2014

20 metre listening

Seems that 20 metres continues to be active with DX this evening.  Currently listening to OD5ZZ from Tripoli, Lebanon.  The band is much more quiet, but then again the weekend contest has no doubt ended.  UT7UJ is active from Kiev, Ukraine towards the upper end of the band.  It is sure nice to hear DX stations again on the bands after so much lack of propagation.  ZS3CX is on from South Africa, T88XT from Palau, VK4LJ from Australia, and ZL2BQ from New Zealand are all quite loud.

20 metre activity picking up

Managed to get enough of the shack cleared out that I could do some listening on 20 metres last evening.  I was pleasantly surprised how active the bands were, including well into the evening.  The contest weekends raise the question in my mind just how dead the bands are as opposed to just how "inactive" the bands are.  It seems that just about every contest weekend I can hear all sorts of DX but otherwise the bands have the appearance of being dead.

I listened to a number of Kuwait stations, New Zealand and mid-Atlantic stations working pile-ups.  After listening to one particular pileup for about an hour, there was momentary lull and I tossed my call sign out to 9K2WA using QRP (5 watts) on SSB and he came right back to me and gave me the obligatory 59 signal report.  (Yeah right...)  But he was about 20 over S9, so who knows how strong I really was on his end.

Monday, February 3, 2014

SWL tonight

Listening to AM broadcast band tonight and am hearing Canadian stations, quite strongly.  31 and 49 metre bands are quite active this evening as well.  Crisp and clear evenings can be fun listening.