Tuesday, February 25, 2025

Simulating Polar Modulation

Note - this page is work-in-progress so expect changes & additions.

We now have some mathematical and practical insight into polar modulation. We also now have some hints regarding it's bandwidth requirements: under certain circumstances both the amplitude and frequency outputs have a high harmonic content. But a practical circuit implementation will impose some bandwidth constraints. For instance, if we use the si5351 for frequency generation, it's output frequency can only be updated at about 12ksps - imposing an upper bandwith on the frequency output of about 6kHz. We therefore want to understand the consequences of these bandwidth restrictions.

 My maths skills are insufficient for me to carry out a theoretical analysis, and I'm not even sure whether it's possible. For instance I was surprised to find that even analysis of a nontrivial FM modulation quickly becomes intractible  - see here

I have therefore sought answers by simulating the algorithm. I've written a C program that internally generates test signals, simulates polar modulation and writes the individual samples into an array. It then displays the fourier transform results of this time-sequence of values. 

The simulation parameters I've chosen are:

  • The simulation should test bandwidths of the amplitude and frequency outputs up to 192ksps.
  • The carrier frequency should be at least 5x this frequency, or about 1MHz.
  • The simulation sampling should be at least 2x this frequency, but make it 4x for safety: ie. 4MHz.
With 256K samples my PC performs a Fourier transform and all other simulation calculations in well under a second. This quick evaluation time nicely allows the spectrum results to be refreshed and viewed whilst interactively changing input parameters. The frequency-width of each of the Fourier transform's output array entry = samplingfrequencynoofsamples15.3Hz, which is more than enough resolution.

The goal with the simulation code is to remove all possible sources of uncertainty or errors so that the results reflect issues with the core modulation technique only. The Hilbert Transform is nontrival and potentially generates slight amplitude and phase errors in its output. For this reason the Hilbert transform has been removed, and replaced by oscillators that directly generate quadrature phase signals. Also the atan2() and power calculation approximations in Guido's original code are replaced by high accuracy calculations.

The core simulation Pseudocode is:

SAMPLES = 1<<18
Fs = 4e6
dt = 1.0/Fs
float output[SAMPLES]
float outputAmplitude
float freqDelta

float f1 = 1600    // set the modulation signal values
float a1 = 1.0
float f2 = 300
float a2 = 1.0

int AmpSubsampling   = Fs/12000    // for 12kHz amplitude updates
int PhaseSubsampling = Fs/12000    // for 12kHz phase updates

for  t = 0..SAMPLES
// calculate the modulating signal
t1 = 2*PI*f1*dt*t
t2 = 2*PI*f2*dt*t
I = a1*cos(t1) + a2*cos(t2)
Q = a1*sin(t1) + a2*sin(t2)

if ( t mod AmpSubsampling == 0) 
outputAmplitude = sqrt(I*I + Q*Q)

if ( t mod PhaseSubsampling == 0)
float phase = atan2(Q, I);
float dp = phase - prev_phase;
prev_phase = phase;

if(dp < 0)   dp += 2*PI; // phase unwrap
if(dp >= PI) dp -= 2*PI; // reverse phase unwrap
freqDelta = dp * Fs/PhaseSubsampling /(2.0*PI)

carrierPhase += 2.0*PI*(fc+freqDelta)*dt
output[t] = outputAmplitude * cos(carrierPhase)

ApplyWindowingFunction(output)
FFTresult[] = FFT_Transform(output)

power[] = convertResultToPowerIndB(FFTresult)

DisplayAsChart(power)

For the Fourier Transform calculation I use this library - it's open-source, quite fast, the code is easily read, and I was already familiar with it, having used it on other projects. Other libraries might be faster, but raw speed is not critical here.

To simulate various conditions, such as amplitude and phase errors that might be introduced by the Hilbert transform, this core simulation code is supplemented with additional calculations.

When I first wrote this code, I spent some time experimenting with it to give myself confidence that it was both doing what was expected, and that I was able to correctly interprete the results. Some experiments were:

  • Temporarily replaced the modulated carrier with pure sinusoid and verified that the result appeared in the predicted FFT "bin".
  • Temporarily generated two carriers close together and verified that two peaks were present in the FFT result and at the predicted location.
  • Temporarily AM modulated the carrier with a low-frequency sinusoid and confirmed the FFT result was a carrier with two side lobes.
  • Reduced and increased the amplitude of the carrier by a factor of 10 and confirmed that the power output changed by 20dB.

Results with 192kHz Sample Rate

Finally, with the sample rate set to 192kHz, I checked the spectrum with two equal amplitude sinusoids, one at 3.5 kHz and the other ranging in frequency from just below 3.5kHz down to just 40 Hz. In all cases the spectrum is virtually perfect:

The horizontal lines are 10dB apart, and the total span is about 12kHz. This is good evidence that the algorithm is working as expected.

Results with 12kHz Sample Rate - slight amplitude delay

The spectrum results are sensitive to the relative delay between the frequency and amplitude outputs. The best results are when the amplitude signal is delayed by approx. 190 master clock ticks (4MHz rate). This corresponds to a delay of a little over half the 12kHz sample clock.

With the sample rate set to 12kHz, and one input set to 3.5kHz, and the other just 130Hz lower, some spurious signals are present at 45dB down:

When the difference frequency increases to 500Hz, many more spurious signals appear:



At a difference frequency of 1000Hz, the spurious signals have continued to grow but the nearby peaks remain about 40dB down:


With a difference frequency of 1500Hz the spurious signal peaks are 30dB down:



When the difference frequency reaches 2000Hz, the spurious signal peaks are 25dB down:



With a difference frequency of 2500Hz, the spurious signal peaks are <25dB down:



Finally, with a difference frequency of 3000Hz, the spurious signal peaks are 20dB down:


A similar pattern emerges with different sample rates - with a higher sample rate and the same difference-frequency the power of the spuri are lower (and vice versa).

Results with 12kHz Frequency Sample Rate, Increased Amplitude Sample Rate

...tbd...

Sensitivity to Amplitude Variation

In the following charts, the frequencies are kept constant at the standard IMD test tones of 700Hz and 1900Hz , and the 700Hz amplitude is varied:

Equal amplitude:


700Hz at 0.9 amplitude:


700Hz at 0.8 amplitude:



700Hz at 0.5 amplitude:


700Hz at 0.1 amplitude:




To Follow (maybe):

  • Source of errors arising from lower sampling rate
  • Alternative phase unwrapping code?
  • Hardware configuration and results of tests on the hardware
  • Indications of the algorithm's sensitivity to 
    • Hilbert transform phase & amplitude errors
    • Delays between the amplitude & frequency outputs










 

No comments:

Post a Comment