Sunday, December 28, 2014

BPSK vs. FSK/MSK

In a previous post I pondered briefly about BPSK (used in PSK31) as compared to FSK. Instead of traditional frequency-shift keying, in BPSK information is transmitted by patterns of polarity-reversals (sometimes called 180-degree phase shifts). One way to think about this would be to swap antenna terminals on each phase reversal.

BPSK uses a 180 degree phase shift when encoding a zero bit in a varicode character.  By way of review, BPSK uses a sinusoid of constant amplitude and a 180 degree phase shift to represent a binary 1 as opposed to a binary 0.

Now, the problem with this in radio circuits is the phase reversal if hard keyed will result in a lot of splatter and the accompanying bandwidth.  So, in radio circuits as discussed in my series about PSK31 on the arduino, we typically ramp the sinusoid level down to zero at the phase change points to eliminate this splatter and shift the phase reversal to the middle of the bit time.  PSK31 encodes a zero bit as a phase reversal and a one bit as no phase change.  In other aspects however PSK31 is BPSK.

In thinking about BPSK vs. FSK or more accurately, MSK (Minimum Shift Keying) I found myself pondering whether they are functionally equivalent.

MSK is basically FSK with the shift set to ½ the baud rate.  Realistically this is the smallest shift you can use without trading off transmission speed.  PSK31 uses a 31.25 baud transmission speed.  So, if we were going to encode a 31.25 baud data transmission using MSK, our keying shift would be 1/4 of the data rate either side of the transmit center frequency.

31.25 baud / 2 = 15.625 / 2 = 7.8125 Hz

If you think of the phase of a carrier that is 7.8125 Hz below the transmit center frequency, it will lag by 90 degrees after 32 mS, and at 7.8125 Hz above, it will lead by 90 degrees after 32 mS for a difference of 180 degrees.

So MSK appears to be functionally equivalent to BPSK while using +90 and -90 degree shifts instead of 0 and 180 degree shifts.

An advantage to this approach is that the resultant signal has no amplitude modulated component and so non-linear amplification techniques may be utilized greatly simplifying transmitter design.  It does require the ability to do phase continuous frequency changes however.

Hmm...

Ok, so to give this concept a play around, I decided to use all the recent work I did on the Minima to implement 1 Hz tuning on the Si570 and see if I could implement a decode-able PSK31 varicode message using MSK techniques with the Si570.

The Si570 is technically capable of 0.42 Hz frequency precision, but for this experiment, I will use  8 Hz as the frequency shift above and below the transmit frequency instead of 7.8125 Hz.

At 7.8125 Hz, 360 degrees of phase change takes 128 ms.  90 degrees of phase change requires 128/4 = 32 ms.

At 8 Hz, 360 degrees of phase change takes 125 ms.  90 degrees of phase change requires 125/4 = 31.25 ms.

I suspect that most PSK31 decoding applications will be able to deal with this difference.

Having modified my recent PSK31 code to drive the Si570 oscillator rather than generate audio, I have run into a number of problems.  I suspected that the i2c communications library that comes with the Arduino IDE would require interrupts to be enabled, which is true.  If you try to call the Si570 code from within a timer interrupt, it will hang the device.

Enabling interrupts around the Si570 call within the timer ISR cures the hanging problem, but fails to communicate with the Si570 to set the frequency.  I suspect that while the library is returning quickly, the i2c communications doesn't complete until sometime later.

Moving the setFrequency() call out of the ISR generates MSK, but it appears that there are bits being lost.  The ISR is completing in 1.040 us, but is not accurately generating all of the frequency shifts.  My suspicion is that the wire library is returning quickly, but that its own interrupt are not completing in a timely fashion to allow precise control over when frequency shifts are happening.  I will have to do some measurements on the i2c communications and put some debugging pin toggles in the wire library to measure how long things are taking to complete.

More to come...