Demodulating APCO P25 signals

Hi,

I’m trying to demodulate P25 signals using GNURadio.

The specification says I should be able to use a single common DQPSK
receiver to recover either the 4 level FM (C4FM) or the CQPSK signals -
the difference being channel bandwidth (12.5KHz vs 6.25KHz) and that the
DQPSK is also amplitude as well as phase modulated. For my first attempt
I’ve used the GNURadio DQPSK block - here’s what I’ve done:

* Capture live data using usrp_rx_cfile.py (the sampling rate is
  256KS/S so over 2MB for a short sample) [#1]. A screen capture of
  the FFT (peak hold) can be found at [#2].
* Extract a 12.5KHz channel the capture and write the complex
  baseband signal to file [#3]. So the spectrum now looks like [#4]
  and an oscope snapshot is shown in [#5]. The final display seems
  to show a phase-shifted signal so I am pretty confident this far
  is ok.
* Wrote a program [#6] to take the complex baseband sample, resample
  it (so the sampling rate is an integer multiple of the symbol rate
  and at least 4x the highest possible component frequency of the
  signal), and demodulate it using the DQPSK block. The output is
  the dibit stream corresponding to the signals.

I am not convinced the output its right - I’m not finding the frame sync
sequence that should be present in the symbol stream. I’m thinking that
perhaps the standard block isn’t suitable for my use. Can anyone advise?

The other thing that causes me to think its not right is that according
the spec P25 uses a form of DQPSK where each successive symbol is
shifted in phase from its predecessor by 45 degrees (pi/4 radians). Yet
the spec also includes the following table which seems to shows a 90
shift between symbols. I am confused about the spec and unsure as to
what the DQPSK block expects.

Dibits
Symbol
CQPSK Phase Change (degrees)
C4FM Deviation (KHz)
01
+3
+135
+1.8
00
+1
+45
+0.6
10
-1
-45
-0.6
11
-3
-135
-1.8

So, is this really a pi/4 encoding or pi/2? Is the DQPSK block suitable
for demodulating P25? Am I using sensible values for the M&M clock
recovery/channel filter? Are there any other obvious mistakes?

On a related note, there’s a demodulator for a very similar system
(RD-LAP) described at http://radiorausch.googlepages.com. The author has
much more signal processing chops than I (the described code doesn’t use
the DQPSK demod block but a custom one). Sadly, there’s no code or
contact email there. If anyone knows the author perhaps they’ll point
them to me so I can beg or borrow that code.

Steve

[1] original signal
http://www.sedition.org.au/proj/browser/trunk/samples/sample-complex-256KSS.dat?format=raw
as capured by usrp_rx_cfile (2MB file)
[2] FFT peak values of original sampled signal
http://www.sedition.org.au/proj/attachment/wiki/DemodulatorPage/original-sample-fft-peak.png?format=raw
[3] complex baseband signal
http://www.sedition.org.au/proj/browser/trunk/samples/baseband-complex-256KSS.dat?format=raw
(2MB file)
[4] FFT peak values for baseband signal
http://www.sedition.org.au/proj/attachment/wiki/DemodulatorPage/baseband-fft-peak.png?format=raw
[5] oscilloscope snapshot of part of the baseband signal
http://www.sedition.org.au/proj/attachment/wiki/DemodulatorPage/baseband-oscope-snapshot.png?format=raw
[6] Demodulator program demod_file_p25.py
http://www.sedition.org.au/proj/browser/trunk/python/file_demod_p25.py?format=raw
(warning for svn trunk users: this code still uses gr.flow_graph!)

stevie.glass wrote:

* Capture live data using usrp_rx_cfile.py (the sampling rate is
  frequency of the signal), and demodulate it using the DQPSK

radians). Yet the spec also includes the following table which seems
+1.8
-135
doesn’t use the DQPSK demod block but a custom one). Sadly, there’s no
code or contact email there. If anyone knows the author perhaps
they’ll point them to me so I can beg or borrow that code.

Steve

Your oscope signal of the baseband looks like good, clean QPSK, though,
so you’re on the right track. The table you’ve posted is definitely pi/4
DQPSK. What this does is shift the constellation by 45 degrees every
symbol, which means that what used to be a 0 degree phase shift (00)
becomes a +45 degree phase shift. The idea here is to minimize the phase
transition between successive symbols so the maximum is +135 degrees
instead of +180. It’s a minor change in the modulator that helps lower
the bandwidth of the signal.

The big problem, though, is that the DQPSK block in GNU Radio doesn’t do
the pi/4 coding scheme. You’ll have to work on it to adjust the rotation
by +45 degrees each symbol. This should be fairly easy to do.

Tom

Tom R. wrote:

stevie.glass wrote:

Your oscope signal of the baseband looks like good, clean QPSK,
though, so you’re on the right track. The table you’ve posted is
definitely pi/4 DQPSK. What this does is shift the constellation by 45
degrees every symbol, which means that what used to be a 0 degree
phase shift (00) becomes a +45 degree phase shift. The idea here is to
minimize the phase transition between successive symbols so the
maximum is +135 degrees instead of +180. It’s a minor change in the
modulator that helps lower the bandwidth of the signal.

And decrease the linearity demands on the amplifier as a result.

On 2/19/08, Tom R. [email protected] wrote:

The idea here is to minimize the phase
transition between successive symbols so the maximum is +135 degrees
instead of +180. It’s a minor change in the modulator that helps lower
the bandwidth of the signal.

This prevents the passband envelope from passing through zero
amplitude, and allows the transmitter PA more leeway in terms of
linearity and spectral regrowth.


Johnathan C.
Corgan Enterprises LLC
http://corganenterprises.com/

Thanks to everyone for all the help and comments. I shall have a close
look
at the PSK demodulator to see if I can make the change. I note from an
earlier email that Jonathan had worked on a pi/4 DQPSK demodulator so
before
I start I’ll ask if that code was ever finalized and whether its
available?

Steve