From my reading, I see that there are two ways people usually do carrier synchronization:
Decision directed, where the transmitted symbols are unknown are the receiver, decisions are made, and then an error is computed. This assumes the receiver knows the type of signal was sent (in order to make the symbol decisions).
Data aided, where there is some known symbol sequence that is used for adjusting the phase and drive the error to zero.
Are there any carrier synchronization techniques which are non-data-aided and blind in the sense that all they require are IQ samples? I'm thinking of a scenario where I could give the technique a QPSK signal or a 16-QAM signal and the frequency offset would be fixed for both signals.
The best idea I have so far is to use a combination of signal identification and one of the two methods above (IQ samples $\rightarrow$ Signal ID alg. $\rightarrow$ Choose correct traditional technique). Maybe this is a good way to go about it, but if there is some more formal method, I am unsure.
Edit #1
Things that I know or have existing ways to estimate:
- Symbol rate
- Pulse shape
- Bandwidth
- Equally likely symbols
- Modulation could be PSK or QAM
- Assuming a single carrier system
Edit #2
The fourth power method is something that I known of but not in the way that is being described by Dan and Marcus. Apparently can be used for general constellations:
% make some random constellation by choosing 10 points within a 10-by-10 grid
constSize = 10;
iComponent = 10*(rand(constSize , 1)-0.5);
qComponent = 10*(rand(constSize , 1)-0.5);
const = iComponent + 1j*qComponent;
symbols = const(randi([1, length(const)], 1000, 1));
pulseFilter = rcosdesign(rolloff, span, sps, 'sqrt');
basebandSig = upfirdn(symbols, pulseFilter, sps);
basebandSig = exp(1j*2*pi*f0*[0:length(basebandSig)-1]'/sampleRate) .* basebandSig; % adding frequency offset f0 Hertz
basebandSig4 = basebandSig.^4;
% Fourth power estimate
fax = -sampleRate/2:sampleRate/nfft:sampleRate/2-1/nfft;
fftBasebandSig4 = fftshift(fft(basebandSig4));
[~, maxInd] = max(abs(fftBasebandSig4));
f0Hat = fax(maxInd)/4;
The problem is I don't fully understand what is happening. I understand for BPSK or QPSK how raising to the fourth power, all the points go to a single phase and then you can see the frequency offset but for the random constellation I generated, this doesn't happen.
To try and understand what is happening I plotted what happens to the signal when raising to the fourth power:
I see more points around (0, 0), but this also happens if I raise to the fifth power, as well as a peak at 5x the true frequency offset. What is special about the fourth power and do raising to other powers ever offer any benefit? (For a classic M-PSK constellation, you'd raise to the $M^{th}$ power)
Edit #3
In case of future readers, between the accepted answer and the paper, Blind estimation of frequency offset in the presence of unknown multipath, I was able to gain a better grasp of the "raising the oversampled signal to a power" method.