Sunday, January 22, 2012

Updated WSPR beacon

Today I have been working on getting my Propeller WSPR beacon to obey WSPR's timing rules.  I have implemented the notion of TX Percent.  As mentioned in previous posts, I define TX Percent in this way as there is no clear definition in Joe Taylor's documentation on WSPR.

CON
  TXPercent    =       0.20     ' Transmit 20% of the time

VAR
  LONG SecondCnt, Stack[16], Sync

PUB Init
  Sync := ROUND(1.0 / TXPercent * 2.0) ' Calculate when next xmit occurs in minutes
  Sync += (Sync // 2)                  ' Always send on a 2 minute boundary
  Sync *= 60            ' Minutes                                
  SecondCnt := 0        ' Reset the second counter to zero                       
  cognew(Clock, @Stack) ' Start the clock COG


PUB Clock                      ' Runs In its own COG
  repeat
    delay(1000)                ' Update second counter every 1000 ms
    SecondCnt++                ' Should be good for 2^32 seconds or about 136 years


Ok, so TX percent of 20% means you will transmit every 10 minutes.  If you want to change how often you transmit, change the value of TXPercent.  I modified the code to not send when TXPercent is zero as this is listen only mode.

PUB sendCode(stringptr)
  if TXPercent > 0

    repeat strsize(stringptr)
      sendSymbol(byte[stringptr++])


The Clock procedure runs on its own COG and just keeps track of seconds.  The presumption is that you flip on the Propeller board at precisely the start of an even minute.

Lastly, I modified the main routine to wait for the next transmit window.

PUB doInitialize
  repeat
    ' Send symbol set for KO7M CN87 7
    sendCode(string("<paste in your WSPR encoded message here>"))
    noTone
    repeat while SecondCnt // Sync
      delay(100)


I have the updated code running now on 10.140.200 every 10 minutes at about 7 dBm (5 mW).  Look for me in the spot database.  I am seeing about -3 drift typically when running on a 10 minute cycle.  I will have to experiment with better temperature control of the board to see if I can eliminate that.

For those interested, here is the entire beacon Spin code.  I have removed my WSPR coded message.  Please see my previous post on how to create that for your call sign, grid square and power level in dBm.

CON
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

  WMin         =        381     'WAITCNT-expression-overhead Minimum
  RFPin        =         27
  Frequency    = 10_140_200
  ErrorOffset  =       -431

  symbolLength =        683     ' 8192 / 12000 * 1000 = milliseconds
  TXPercent    =       0.20     ' Transmit 20% of the time or about every 10 minutes


OBJ
  Freq : "Synth"
 
VAR
    LONG SecondCnt, Stack[16]
    LONG Sync
   
PUB Main
  doInitialize
  repeat
    ' Send symbol set for KO7M CN87 7
    sendCode(string("<paste your own WSPR coded message here>"))

    noTone
    repeat while SecondCnt // Sync
      delay(100)

  
PUB doInitialize
  Sync := ROUND(1.0 / TXPercent * 2.0) ' Calculate when next transmission occurs in minutes
  Sync += (Sync // 2)                  ' Make sure we always send on a 2 minute boundary
  Sync *= 60                   ' Convert minutes to seconds                                                
  SecondCnt := 0               ' Reset the second counter to zero                       
  cognew(Clock, @Stack)        ' Start the clock COG
 
PUB sendCode(stringptr)
  if TXPercent > 0             ' TXPercent of zero indicates we are not transmitting                       
    repeat strsize(stringptr)
      sendSymbol(byte[stringptr++])


PUB sendSymbol(char)
  case char
   "0":
    sendTone(-3)
    delay(symbolLength)

   "1":
    sendTone(-1)
    delay(symbolLength)
   "2":
    sendTone(1)
    delay(symbolLength)
   "3":
    sendTone(3)
    delay(SymbolLength)

  
PUB sendTone(tone)
  Freq.Synth("A",RFPin, Frequency + tone + ErrorOffset)


PUB noTone
  Freq.Synth("A",RFPin, 0)


PUB delay(Duration)
  waitcnt(((clkfreq / 1_000 * Duration - 3932) #> WMin) + cnt)


PUB Clock                      ' Runs In its own COG
  repeat
    delay(1000)                ' Update second counter every 1000 ms
    SecondCnt++                ' Should be good for 2^32 seconds or about 136 years

No comments:

Post a Comment