mrfioc2
2.3.0
|
Files | |
file | mrfFracSynth.c |
Support routines for the Micrel SY87739L Fractional-N Synthesizer. | |
Classes | |
struct | PostDivideStruct |
struct | CorrectionStruct |
struct | CorrectionValStruct |
struct | FracSynthComponents |
Macros | |
#define | DEBUG_PRINT /* Debug printing always enabled for this module */ |
#define | MAX_CORRECTION_RATIO (17./14.) /* Maximum value for correction term. */ |
#define | MAX_VCO_FREQ 729.0 /* Maximum frequency for voltage-controlled oscillator */ |
#define | MIN_VCO_FREQ 540.0 /* Minimum frequency for voltage-controlled oscillator */ |
#define | MIN_P_VALUE 17 /* Minimum val for integer part of fractional frequency */ |
#define | MAX_FRAC_DIVISOR 31 /* Maximum divisor for fractional frequency value */ |
#define | NUM_POST_DIVIDES 31 /* Number of unique post-divider values */ |
#define | NUM_POST_DIVIDE_VALS 32 /* Number of post-divider codes */ |
#define | NUM_CORRECTIONS 23 /* Number of valid correction values (plus one) */ |
#define | NUM_CORRECTION_VALS 8 /* Number of correction value codes */ |
#define | MAX_ERROR 100.0 /* Artifical error maximum */ |
#define | ZERO_THRESHOLD 1.0e-9 /* Floating point threshold for zero detection */ |
#define | CONTROL_MDIV_BITS 3 /* Denominator of correction term */ |
#define | CONTROL_NDIV_BITS 3 /* Numerator of correction term */ |
#define | CONTROL_POSTDIV_BITS 5 /* Post-Divider */ |
#define | CONTROL_MFG_BITS 3 /* Must Be Zero */ |
#define | CONTROL_P_BITS 4 /* Integer part of fractional frequency */ |
#define | CONTROL_QPM1_BITS 5 /* Value for Q(p-1) term of fractional frequency */ |
#define | CONTROL_QP_BITS 5 /* Value for Q(p) term of fractional frequency */ |
#define | CONTROL_PREAMBLE_BITS 4 /* Must Be Zero */ |
#define | CONTROL_MDIV_SHIFT 0 /* Denominator of correction term */ |
#define | CONTROL_NDIV_SHIFT 3 /* Numerator of correction term */ |
#define | CONTROL_POSTDIV_SHIFT 6 /* Post-Divider */ |
#define | CONTROL_MFG_SHIFT 11 /* Must Be Zero */ |
#define | CONTROL_P_SHIFT 14 /* Integer part of fractional frequency */ |
#define | CONTROL_QPM1_SHIFT 18 /* Value for Q(p-1) term of fractional frequency */ |
#define | CONTROL_QP_SHIFT 23 /* Value for Q(p) term of fractional frequency */ |
#define | CONTROL_PREAMBLE_SHIFT 28 /* Must Be Zero */ |
#define | CONTROL_MDIV_MASK (((1 << CONTROL_MDIV_BITS) - 1) << CONTROL_MDIV_SHIFT) |
#define | CONTROL_NDIV_MASK (((1 << CONTROL_NDIV_BITS) - 1) << CONTROL_NDIV_SHIFT) |
#define | CONTROL_POSTDIV_MASK (((1 << CONTROL_POSTDIV_BITS) - 1) << CONTROL_POSTDIV_SHIFT) |
#define | CONTROL_MFG_MASK (((1 << CONTROL_MFG_BITS) - 1) << CONTROL_MFG_SHIFT) |
#define | CONTROL_P_MASK (((1 << CONTROL_P_BITS) - 1) << CONTROL_P_SHIFT) |
#define | CONTROL_QPM1_MASK (((1 << CONTROL_QPM1_BITS) - 1) << CONTROL_QPM1_SHIFT) |
#define | CONTROL_QP_MASK (((1 << CONTROL_QP_BITS) - 1) << CONTROL_QP_SHIFT) |
#define | CONTROL_PREAMBLE_MASK (((1 << CONTROL_PREAMBLE_BITS) - 1) << CONTROL_PREAMBLE_SHIFT) |
#define | CORRECTION_DIV_14 5 /* Numerator or denominator of 14 */ |
#define | CORRECTION_DIV_15 7 /* Numerator or denominator of 15 */ |
#define | CORRECTION_DIV_16 1 /* Numerator or denominator of 16 */ |
#define | CORRECTION_DIV_17 3 /* Numerator or denominator of 17 */ |
#define | CORRECTION_DIV_18 2 /* Numerator or denominator of 18 */ |
#define | CORRECTION_DIV_31 4 /* Numerator or denominator of 31 */ |
#define | CORRECTION_DIV_32 6 /* Numerator or denominator of 32 */ |
Functions | |
epicsShareExtern epicsStatus | mrfSetEventClockSpeed (epicsFloat64 InputClockSpeed, epicsUInt32 InputControlWord, epicsFloat64 ReferenceFreq, epicsFloat64 *OutputClockSpeed, epicsUInt32 *OutputControlWord, epicsInt32 PrintFlag) |
epicsShareExtern epicsUInt32 | FracSynthControlWord (epicsFloat64 DesiredFreq, epicsFloat64 ReferenceFreq, epicsInt32 debugFlag, epicsFloat64 *Error) |
epicsShareExtern epicsFloat64 | FracSynthAnalyze (epicsUInt32 ControlWord, epicsFloat64 ReferenceFreq, epicsInt32 PrintFlag) |
epicsExportRegistrar (FracSynthRegistrar) | |
#define CONTROL_MDIV_BITS 3 /* Denominator of correction term */ |
Definition at line 139 of file mrfFracSynth.c.
#define CONTROL_MDIV_MASK (((1 << CONTROL_MDIV_BITS) - 1) << CONTROL_MDIV_SHIFT) |
Definition at line 165 of file mrfFracSynth.c.
#define CONTROL_MDIV_SHIFT 0 /* Denominator of correction term */ |
Definition at line 152 of file mrfFracSynth.c.
#define CONTROL_MFG_BITS 3 /* Must Be Zero */ |
Definition at line 142 of file mrfFracSynth.c.
#define CONTROL_MFG_MASK (((1 << CONTROL_MFG_BITS) - 1) << CONTROL_MFG_SHIFT) |
Definition at line 168 of file mrfFracSynth.c.
#define CONTROL_MFG_SHIFT 11 /* Must Be Zero */ |
Definition at line 155 of file mrfFracSynth.c.
#define CONTROL_NDIV_BITS 3 /* Numerator of correction term */ |
Definition at line 140 of file mrfFracSynth.c.
#define CONTROL_NDIV_MASK (((1 << CONTROL_NDIV_BITS) - 1) << CONTROL_NDIV_SHIFT) |
Definition at line 166 of file mrfFracSynth.c.
#define CONTROL_NDIV_SHIFT 3 /* Numerator of correction term */ |
Definition at line 153 of file mrfFracSynth.c.
#define CONTROL_P_BITS 4 /* Integer part of fractional frequency */ |
Definition at line 143 of file mrfFracSynth.c.
#define CONTROL_P_MASK (((1 << CONTROL_P_BITS) - 1) << CONTROL_P_SHIFT) |
Definition at line 169 of file mrfFracSynth.c.
#define CONTROL_P_SHIFT 14 /* Integer part of fractional frequency */ |
Definition at line 156 of file mrfFracSynth.c.
#define CONTROL_POSTDIV_BITS 5 /* Post-Divider */ |
Definition at line 141 of file mrfFracSynth.c.
#define CONTROL_POSTDIV_MASK (((1 << CONTROL_POSTDIV_BITS) - 1) << CONTROL_POSTDIV_SHIFT) |
Definition at line 167 of file mrfFracSynth.c.
#define CONTROL_POSTDIV_SHIFT 6 /* Post-Divider */ |
Definition at line 154 of file mrfFracSynth.c.
#define CONTROL_PREAMBLE_BITS 4 /* Must Be Zero */ |
Definition at line 146 of file mrfFracSynth.c.
#define CONTROL_PREAMBLE_MASK (((1 << CONTROL_PREAMBLE_BITS) - 1) << CONTROL_PREAMBLE_SHIFT) |
Definition at line 172 of file mrfFracSynth.c.
#define CONTROL_PREAMBLE_SHIFT 28 /* Must Be Zero */ |
Definition at line 159 of file mrfFracSynth.c.
#define CONTROL_QP_BITS 5 /* Value for Q(p) term of fractional frequency */ |
Definition at line 145 of file mrfFracSynth.c.
#define CONTROL_QP_MASK (((1 << CONTROL_QP_BITS) - 1) << CONTROL_QP_SHIFT) |
Definition at line 171 of file mrfFracSynth.c.
#define CONTROL_QP_SHIFT 23 /* Value for Q(p) term of fractional frequency */ |
Definition at line 158 of file mrfFracSynth.c.
#define CONTROL_QPM1_BITS 5 /* Value for Q(p-1) term of fractional frequency */ |
Definition at line 144 of file mrfFracSynth.c.
#define CONTROL_QPM1_MASK (((1 << CONTROL_QPM1_BITS) - 1) << CONTROL_QPM1_SHIFT) |
Definition at line 170 of file mrfFracSynth.c.
#define CONTROL_QPM1_SHIFT 18 /* Value for Q(p-1) term of fractional frequency */ |
Definition at line 157 of file mrfFracSynth.c.
#define CORRECTION_DIV_14 5 /* Numerator or denominator of 14 */ |
Definition at line 178 of file mrfFracSynth.c.
#define CORRECTION_DIV_15 7 /* Numerator or denominator of 15 */ |
Definition at line 179 of file mrfFracSynth.c.
#define CORRECTION_DIV_16 1 /* Numerator or denominator of 16 */ |
Definition at line 180 of file mrfFracSynth.c.
#define CORRECTION_DIV_17 3 /* Numerator or denominator of 17 */ |
Definition at line 181 of file mrfFracSynth.c.
#define CORRECTION_DIV_18 2 /* Numerator or denominator of 18 */ |
Definition at line 182 of file mrfFracSynth.c.
#define CORRECTION_DIV_31 4 /* Numerator or denominator of 31 */ |
Definition at line 183 of file mrfFracSynth.c.
#define CORRECTION_DIV_32 6 /* Numerator or denominator of 32 */ |
Definition at line 184 of file mrfFracSynth.c.
#define DEBUG_PRINT /* Debug printing always enabled for this module */ |
Definition at line 92 of file mrfFracSynth.c.
#define MAX_CORRECTION_RATIO (17./14.) /* Maximum value for correction term. */ |
Definition at line 116 of file mrfFracSynth.c.
#define MAX_ERROR 100.0 /* Artifical error maximum */ |
Definition at line 127 of file mrfFracSynth.c.
#define MAX_FRAC_DIVISOR 31 /* Maximum divisor for fractional frequency value */ |
Definition at line 120 of file mrfFracSynth.c.
#define MAX_VCO_FREQ 729.0 /* Maximum frequency for voltage-controlled oscillator */ |
Definition at line 117 of file mrfFracSynth.c.
#define MIN_P_VALUE 17 /* Minimum val for integer part of fractional frequency */ |
Definition at line 119 of file mrfFracSynth.c.
#define MIN_VCO_FREQ 540.0 /* Minimum frequency for voltage-controlled oscillator */ |
Definition at line 118 of file mrfFracSynth.c.
#define NUM_CORRECTION_VALS 8 /* Number of correction value codes */ |
Definition at line 125 of file mrfFracSynth.c.
#define NUM_CORRECTIONS 23 /* Number of valid correction values (plus one) */ |
Definition at line 124 of file mrfFracSynth.c.
#define NUM_POST_DIVIDE_VALS 32 /* Number of post-divider codes */ |
Definition at line 123 of file mrfFracSynth.c.
#define NUM_POST_DIVIDES 31 /* Number of unique post-divider values */ |
Definition at line 122 of file mrfFracSynth.c.
#define ZERO_THRESHOLD 1.0e-9 /* Floating point threshold for zero detection */ |
Definition at line 128 of file mrfFracSynth.c.
epicsExportRegistrar | ( | FracSynthRegistrar | ) |
epicsShareExtern epicsFloat64 FracSynthAnalyze | ( | epicsUInt32 | ControlWord, |
epicsFloat64 | ReferenceFreq, | ||
epicsInt32 | PrintFlag | ||
) |
ControlWord | = (input) The control word bit pattern to analyze. |
ReferenceFreq | = (input) SY87739L input reference frequency in MegaHertz. |
PrintFlag | = (input) Flag to control output messages. Output levels correspond to the DEBUGPRINT output levels: DP_NONE (0) = No printed output, just return the effective output frequency. DP_ERROR (2) = Display any programming errors detected in the control word DP_DEBUG (5) = Display the actual values of the fields in the control word, along with the constituent parts of the output frequency (VCO frequency, correction term, reference freq.) |
Definition at line 844 of file mrfFracSynth.c.
epicsShareExtern epicsUInt32 FracSynthControlWord | ( | epicsFloat64 | DesiredFreq, |
epicsFloat64 | ReferenceFreq, | ||
epicsInt32 | debugFlag, | ||
epicsFloat64 * | Error | ||
) |
This routine will take a desired output frequency (expressed in MegaHertz)and a reference frequency (also expressed in MegaHertz) and create a control word for the Micrel SY877391L Fractional-N Synthesizer chip that will produce an output frequency as close as possible to the desired frequency. The routine also returns an error value (expressed in parts-per-million) between the actual output frequency and the desired output frequency.
A complete description of how the Micrel SY87739L chip works is way beyond the scope of a function header comment. The reader who wants a complete understanding of what this routine is doing should refer to the Micrel SY87739L product description sheet available at: www.micrel.com
A brief description of the chip programming is useful, however, and is provided here:
The output frequency is described by the following formulae:
F(out) = F(vco) / PostDiv
where F(vco) is the frequency generated by a voltage-controlled oscillator, and PostDiv is a frequency divider value between 1 and 60 (not inclusive). The PostDiv value must be chosen so that the VCO frequency is within its operating range of 540 - 729 MHz. The VCO frequency is given by:
F(vco) = C * F(frac) * F(ref)
where C is a "Correction Factor" (also referred to as the "wrapper correction" in the documentation0 expressed as (N/M) where N and M are from the set {14, 15, 16, 17, 18, 31, 32}. Not all combinations, however, are legal. F(frac) is the fractional frequency produced by a fractional-N P/P-1 divider circuit. F(ref) is the input reference frequency to the Micrel chip. Typically it is 27 MHz, although in the MRF timing boards it is 24 MHz. The fractional frequency is basically a multiplier for the reference frequency. It is expressed as a rational number with a divisor less than 32 and is given by:
F(frac) = P - (Q(p-1) / (Q(p) + Q(p-1)))
where P is the integer part of the fractional frequency, Q(p) is the number of clock periods where the reference clock is divided by P and Q(p-1) is the number of clock periods where the reference clock is divided by P-1. A hardware implementation of Bresenham's algorithm is used to evenly space out the P and P-1 divisions. Beyond this, you'll have to read the manual for further details.
The routine works by doing an exhaustive search (with some optimizations) of the parameter space {C, Q(p), Q(p-1), PostDiv}. P is predetermined by F(out) and PostDiv, so it does not need to be searched. The Q(p), Q(p-1) search is accomplished by searching all the numerators for the denominator (Q(p) + Q(p-1)) that produce a fraction less than 1. Although an exhaustive search is not the most efficient way to optimize a 4-parameter space, it turns out that the dimensions of each parameter are not that big. PostDiv only has 31 unique values, and we only search the values that produce a valid F(vco). When you rule out duplications and illegal combinations it turns out that C only has 22 valid values, and if you arrange them in ascending order, you only have to search until the error value stops decreasing. For Q(p) and Q(p-1), we only have to search 31 denominators and for each denominator we only have to search n-1 numerators. This gives us n(n+1)/2, or 465 (for n=30) possible numerator/denominator pairs to search, although we stop immediately if we find a denominator that exactly divides the desired fractional frequency.
If we search 22 correction factors for each numerator/denominator pair, and we repeat the process for each of 31 possible PostDiv values, we get a worst case number of 317,130 possible combinations. In practice, the VCO frequency limitations (between 540 and 729 Megahertz) will usually eliminate most of the 31 possible PostDiv values. Given the other optimizations mentioned above, the worst case number is a pretty pathological example. In most cases the number of combinations actually searched will be far less than that.
DesiredFreq | = (input) Desired output frequency in MegaHertz. |
ReferenceFreq | = (input) SY87739L input reference frequency in MegaHertz. |
debugFlag | = (input) Flag for debug output. If the value is 4 (DP_INFO) or higher, the routine will print the value of the control word and the frequency actually produced. |
Error | = (output) Error between the actual output frequency and the desired output frequency. Expressed in parts-per-million. |
Definition at line 552 of file mrfFracSynth.c.
epicsShareExtern epicsStatus mrfSetEventClockSpeed | ( | epicsFloat64 | InputClockSpeed, |
epicsUInt32 | InputControlWord, | ||
epicsFloat64 | ReferenceFreq, | ||
epicsFloat64 * | OutputClockSpeed, | ||
epicsUInt32 * | OutputControlWord, | ||
epicsInt32 | PrintFlag | ||
) |
This routine will determine the system's event clock speed (in Megahertz) and/or the value for the fractional synthesizer control word given at least one of these two values.
If the InputClockSpeed parameter is specified (not zero), the routine will compute the value of the fractional synthesizer control word to produce that frequency.
If the InputControlWord parameter is specified (not zero), the routine will check the control word for programming errors and return the actual frequency (in Megahertz) produced by that control word.
If neither parameter is specified, the routine will output a default event clock frequency and a default control word.
If both parameters are specified, the routine will make sure the frequency generated by the control word is within 100 ppm of the desired clock speed.
If no errors are encountered, the routine will return both the final event clock speed and the fractional synthesizer control word. If errors are encountered, both output parameters will contain zero.
InputClockSpeed | = (input) Desired event clock speed in Megahertz. 0.0 means no clock speed specified. |
InputControlWord | = (input) Desired value for the fractional synthesizer control word. 0 means no control word specified. |
ReferenceFreq | = (input) SY87739L input reference frequency in MegaHertz. |
OutputClockSpeed | = (output) The input or computed value for the event clock speed |
OutputControlWord | = (output) The input or computed value for the fractional synthesizer control word. |
PrintFlag | = (input) Flag to control output messages. Output levels correspond to the DEBUGPRINT output levels: DP_NONE (0) = Only display errors that prevent us from returning the event clock speed and the control word. DP_ERROR (2) = Display any programming errors detected in the control word. DP_WARN (3) = Display warning messages such as the one warning that we are using the default event clock frequency. DP_INFO (4) = Display the value of the computed control word, its actual output frequency, and the error (in ppm) between the desired and actual frequencies. DP_DEBUG (5) = Display the actual values of the fields in the control word, along with the constituent parts of the output frequency (VCO frequency, correction term, reference freq.) |
Definition at line 365 of file mrfFracSynth.c.