PSK31 Audio Beacon     

PSK31 Beacon


Project Description


App #1: Tone Gen

Description

Source Code


PSK31 Beacon

Description

Schematic

PCB Layout

Source Code


Programming the SX

Useful SX Links

SX28 Overview

Beaconing Guide


Back to 
Digital Homebrewing Home Page

 


SOFTWARE DESCRIPTION & SOURCE CODE

   Click HERE to view the source code listing.

This source file may also be downloaded by right-clicking on that same link and saving the file to your local computerRemember to change the filename extension to .src in order for the SX editor to recognize it.

Beacon String Construct

The Beacon software is programmed to transmit two types of data in sequence:

1) Idle Stream - Upon transmit initiation, the Beacon sends a series of 64 zeros to allow the PSK31 receiving system and decoder to synchronize for the data reception that follows. In some PSK31 applications this idle stream time allows the decoding software to measure signal "IMD", an indication of energy present in adjacent sidebands and somewhat of a figure of merit for the received signal.

2) Data String - Immediately following the idle stream of zeros, the Beacon begins sending the data string that will ultimately be displayed on the receiving side of the communications channel. This is the custom-programmed sequence of ASCII characters. The data string may be of any length, and is limited only by available memory.

The SX chip provided in this kit comes pre-programmed with the information specified in the initial ordering process. This beacon string is "burned" into the program memory and is transferred to internal RAM memory when power is applied. Whenever the START pushbutton is actuated or the CONTINUOUS jumper put in place, the string in RAM memory is encoded and audibly transmitted.

Entering Custom Beacon Strings

One may alternatively enter a different text string directly to RAM memory over the RS-232C serial COM port provided on the Beacon board. A separate computer would typically be used to send this new text string to the Beacon. The new text is entered character-by-character into RAM data memory, effectively overwriting the pre-programmed text string that was put there initially at power-up time. But since RAM data memory is volatile (i.e., contents are lost when board power is removed), the custom-entered text string is only present while the power is applied. If power is cycled, the custom text string must be applied again to overwrite the pre-programmed string.

The way to initiate the entry of a custom text string is by having the X7 (CONTINUOUS) jumper in place and holding down the START pushbutton when applying power to the board. You also must have the X0 jumper in place to signify use of the serial COM port. A convenient way to switch the Beacon into this serial-entry mode is to wire the X7 and START lines to a DPDT toggle switch that would ground the respective input lines when this mode is desired. The X0 input line could also be put to a SPDT switch to be grounded for use of the serial port. (Two separate switches are recommended for reasons explained in the section concerning Direct Character Transmission mode.)

Interrupt Timing

For this part of the discussion, it will be assumed that the configuration jumpers are set to produce a 500 Hz carrier frequency, with a nominal interrupt variability of 4 (X2 jumper in place for an RTCC reload value of 197.)

The PSK31 Audio Beacon software is completely interrupt-driven, based on the timeout settings of the real time clock (RTCC). The default setting of the RTCC counter produces an interrupt every 3.94us and the Interrupt Service Routine (ISR) counts two of these interrupts and then signals the presence of a 7.88us interval by setting the SYNC7US software flag. This flag is inspected in a tight loop at the MAIN starting point of the program, and when detected as being set, the whole program sequence begins.

Creating the Carrier Sine Wave

Every 4th time the 7.88us window starts (i.e., at the 31.25us boundaries), the software gets the next 8-bit value from the sine wave look-up table and outputs it to the DAC output port RB. When this process happens 64 times (i.e., when 64 instances of the 31.25us windows have occurred) a single sine wave will have been constructed within a 2ms time period, creating a 500 Hz carrier.

The software keeps track of how many carrier cycles have been generated, and when the count reaches 15 (i.e., at the 31ms interval), the PSK bit window is present and the PSK bit processing begins.

Actually, the recurring 31ms window starts at mid-position of one bit cycle and goes to mid-position of the next bit cycle. It’s done this way so the software can inspect the current / next bit relationship and command a zero-power phase reversal condition at the next end-bit time period, if required.

Creating the Phase Reversals

The bits constituting the Varicode character being sequentially presented for modulation are inspected on a bit-by-bit basis at each 31ms bit processing window. When a "1" is encountered, nothing is done in that window. The sine wave construction continues

However when a "0" is encountered, the rules of PSK31 modulation state that a phase reversal must be forced in the carrier.

The processing gets a little more complicated at this point because we want to reduce the power of the carrier at the time of phase reversals. This action greatly reduces the "glitch" energy at the time of the reversals and makes the resultant tones much more spectrally clean.

A cosine wave look-up table is used to modulate (or "scale") the carrier wave, sample by sample at the 31.25us rate. The cosine table pointer is advanced as each cycle of the carrier is generated.

If the "next bit" of the varicode character to be processed is a "0", the scaling process is turned on at mid-bit position and the remaining 7 carrier cycles of waveform construction occurring in the bit-processing window get scaled per the cosine look-up table. This effectively brings the amplitude of those seven sine waves progressively down to zero, at which point the phase of the carrier is reversed (by changing to a different sine wave look-up table — one that is 180-degrees out of phase from the other one.)

After the phase reversal, the carrier continues to be constructed at every 31.25us interval, and the cosine scaling is still engaged in sync with the carrier cycles. For the next seven cycles, the cosine look-up table routines scale up the carrier such that the carrier is back to full power (no scaling) by mid-bit position.

All this can be more easily understood by considering the oscilloscope screen photo below:

Here we see 15 cycles of the 500 Hz carrier constituting a 31ms bit-processing window. The sequence of characters processed were two sequential zeros – the first being encoded in the phase reversal seen zt the zero-power point on the left, and the second on the right. These points are where the sine wave look-up tables are changed, resulting in the obvious phase reversals. It can also be seen that the cosine "scaling" of the carrier starts at mid position in the bit-processing window and proceeds to zero at the end of the cycle where the reversals occur. The power is then raised in the following 7 cycles of the next window.

Encoding a "T"

Using the PSK31 encoding algorithm for phase reversals (i.e., insert a phase reversal whenever encountering a "0" in the bit stream), we can begin to consider what a composite sequence of bits will look like for an entire character.

In this example, we’ll look at the letter "T", which has a Varicode equivalent bit pattern of 1101101. The sketch below illustrates what one would see with an oscilloscope properly synchronized at the start of the character sequence:

It’s useful at this point to mention that two (or more) consecutive "zeros" constitute a letter gap, thus instructing the decoding engine on the receiving side to start another character processing cycle.

In the diagram below, a letter gap of 0-0 starts off the "T" sequence of bits. Upon encountering each "0", the power level is brought down to zero and the phase is reversed. The power level is then raised back up to 100% by mid-next position, whereupon the "next bit" is inspected to see if another reversal will be needed.

Upon encountering the first "1", the algorithm dictates that no phase reversal occurs, so the power level remains at 100$ (no cosine scaling).

The same happens again upon encountering the second "1", but the next bit after that is a "0" and the power level is reduced in anticipation of the coming phase reversal.

One can easily see these principles in action in the oscilloscope trace in figure 3. The phase reversals can be seen at the point where the power is reduced to zero, which is at the bit-processing intervals (31ms). The square wave superimposed above and below the carrier is the 31ms sync signal present on the Test Point of the processor (bit 3 of port RA.) It can be clearly seen how the current/next bit processing is actually done at the mid-bit position, halfway through the 31ms period window

Producing Different Frequency Carriers

The preceding discussion assumed a 500 Hz carrier and a core interrupt time of 3.94us. With a little software magic, some variability was placed into the program in order to produce two more base carrier frequencies, and 16 sub-variations around each base frequency.

The interrupt structure and timing is actually designed to produce a 2 KHz carrier as the highest base frequency, using a 7.88us sine wave construction. Then, based on the state of the configuration jumpers, we’re able to sample at half-rates to get the 15.75us rate for 1 KHz carrier generation, and 31.25us rate for 500 Hz carrier generation.

Achieving the 16 frequency variations around each of the three base carrier frequencies is achieved by slightly varying the basic underlying interrupt timing mechanism.

The Real Time Clock Counter (RTCC) is clocked by the master 50 MHz oscillator internal to the microcontroller. Interrupts are generated when the RTCC "rolls over" upon a countdown from a preset value, and the governing mechanism for interrupt timing is to preset the RTCC counter at the end of each interrupt cycle. The nominal value of the RTCC preset is "200", and we can go as much as +/- 8 counts before receiving systems lose synchronization with the master 31 baud system timing in the Beacon.

Therefore, RTCCvariable is set to a value between 194 and 209 within the setRTCC routine based on the state of the configuration jumpers X0-through-X3. These four bits give 16 different RTCC preset values that modify the basic system timing of the beacon, which results in an ability to more precisely position the base carriers within about +/- 60 Hz around their nominal values.

The last comment about the software design is that I make extensive use of the look-up table (LUT) capabilities of the SX microcontroller. Using the LUTs, we are able to easily generate two 64-point sine waves — a positive-going one SINETBP and a negative going one (SINETBN) – and a 64 point half cosine waveform (COSTBL). Using a pointer to travel through each table allows easy retrieval of the waveform values which represent a 0-to-1 percentage of the 5 bit values represented in the tables.


Page last modified: November 28, 2001

Copyright 2001 G. Heron, N2APB

n2apb@amsat.org