Thursday, February 2, 2012

WSPR Encoder - "Thinking Out Loud"

I have been pondering why my WSPR encoder routine could be giving me incorrect results.  When I encode my message "KO7M CN87 27" and let the WSPR 2.11 application decode it, I get the following:

<...> KO7M 27

In reading the specification, I see the following:

Special Message Formats
Normal WSPR messages consist of a callsign, 4-digit grid locator, and power level in dBm. These messages are always preferred when appropriate. However, compound callsigns (i.e., callsigns with add-on prefix or suffix) cannot fit into the 28 bits allocated in a standard message. Similarly, 6-digit locators cannot fit into 15 bits. Messages using these components are therefore sent using a two-transmission sequence. For example, if the callsign is PJ4/K1ABC, the 6-digit grid locator is FK52UD, and the power level 37 dBm, the following messages will be sent in alternating transmissions:
PJ4/K1ABC 37
<PJ4/K1ABC> FK52UD 37

If you have special need to use a 6-digit locator with a normal callsign, check the box
Force transmission of 6-digit locator. If the callsign is K1ABC, the 6-digit grid locator FN42AX, and the power level 37 dBm, the following messages will then be sent in alternating transmissions:

K1ABC FN42 37
<K1ABC> FN42AX 37

Callsigns enclosed in angle brackets are actually sent as 15-bit hash codes. If such a code is received by another station before the full callsign has been received, it will be displayed as


on the decoded text line. Once the full callsign has been received, the decoder will thereafter recognize the hash code and fill in the blanks. Two very different callsigns might have the same hash code, but the 15-bit hash-code length ensures that in practice such collisions will be rare.

Please note that messages with compound callsigns or 6-digit locators will not be properly decoded by WSPR versions earlier than 2.0. Further details on message formats can be found in Appendix B, and in the WSPR source code.

Hmmm...  So, if I am reading this correctly, in a normal format message, I am supposed to encode the message as follows:

  1. 28 bits encodes a normal 6 character callsign
  2. 15 bits encodes a 4 character locator
  3. 7 bits encodes the power in dBm.
The special message format from the description above encodes in two messages, the content depends on the format of the data being encoded and whether or not the "Force transmissions of 6-digit locator" checkbox is  set to "checked".

Case 1:
Callsign with slash character in it
In this case, the normal (up to) 6 character callsign is augmented with a slash character (front or back) and up to 3 additional characters.  For example WA0FOO/7, JA2/KJ7ABC, etc.  The 28 bit callsign field and the 15 bit locator are large enough to contain this data while the power is sent in its own normal 7 bit field.  Here is my hypothesis:

  • When encoding WSPR messages, a the callsign field is required to have no more than 6 characters and is required to have a numeric in the third character position.  If the callsign does not match these specifications, spaces are added as neeed.  For example, "K7XX" is encoded as "<space>K7XX<space>".  This I have previously proven before the special formats where encorporated into WSPR.
  • When encoding a special format callsign, I believe that the "/" character and up to three additional characters must be encoded in the 15 bit locator field while the normal callsign is encoded in the callsign field padded with spaces as necessary.
  • The power level goes in the normal 7 bit field.
  • The first message contains the special callsign and power level only.
  • The second message packs up to 6 digits of a locator, space padded as needed into the normal 28 bit callsign field.  A 15 bit hash of the callsign is computed and sent in the 15 bit locator field.  The power is sent normally in its 7 bit field.
This case should allow for adorned callsigns as well as six character locators to be sent in two messages max.

Unanswered Questions
  1. Can the application can detect when decoding whether the callsign adornment belongs on the left or right side of the call?  For example: JA2/WA0AAA vs. WA0AAA/JA2.  I think this could be stored in the encoding of the "/" character.
  2. What is the precise encoding of the "/" character?
  3. Precisely how to calculate the 15 bit hash of the callsign?
Case 2:
Normal unadorned callsign (no slash) and 6 character locator
In this case the first message is a normal message with the extra 2 characters of the locator truncated as indicated in the documentation reference above.  My hypothesis about the remainder of the message is:
  1. The six digit locator is encoded into the 28 bit callsign field.
  2. The 15 bit hash is computed of the callsign and sent in the locator 15 bit field.
  3. The 7 bit power field contains the power level in dBm.

My code to encode the WSPR message doesn't know anything about special formats (yet) but is generating a symbol set that is decoding as if it was the second message a two message set, very much as would be found in case 2 above.  Joe Taylor's spec says that any callsign enclosed in <...> characters is sent as a 15 bit hash.  This points to the locator being incorrectly encoded.  The message I am sending is being decoded as:

<...> KO7M 27

This tells me that my call sign and power are both being encoded correctly because WSPR can decode them.  Since the encoding between the callsign and the locator fields is a different algorithm, the callsign must be encoded correctly and placed in the correct 28 bit callsign field of the WSPR message.  What appears to be wrong is the locator encoding.

The results would match case 1 above, if WSPR thought the locator field was a 15 bit hash, not a locator and that it has not yet received the first message of the two message set.  WSPR would then display precisely what I am seeing.

So, this little exercise has served to narrow my focus to the encoding of the locator field.  I must have some sort of logic error in this part of the code.

More to follow.


  1. you might want to check top of page 7

    "For example, if the callsign is PJ4/K1ABC, the 6-digit grid locator is FK52UD, and the power level 37 dBm, the following messages will be sent in alternating transmissions:

    PJ4/K1ABC 37 FK52UD 37"



  2. may also help