Monday, December 26, 2011

30m Beacon - a 20 min Effort

So how easy was it to Program a CW and QRSS FSK Beacon with the Propeller? See previous post.

Well here is the code of the Main program, followed by the supplied Synthesizer Library. Note: in the Propeller "Spin"Programming Language, line indents (i.e., TABs or spaces) are important. They define the programming constructs for loops and other structures.

The Main Program


CON

  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

  RFPin  = 27

  ReceiverDial = 10_138_700
  TuneOffset   =      1_300

  Frequency = ReceiverDial + TuneOffset          'DC to 128MHz


VAR

OBJ
  Freq : "Synth"
  
PUB Main | i
  repeat
    ' Send my Call via CW
    sendCWstr(string("de WA0UWH"))
    delay(2000)

    ' For fun, Generate 5 QRSS tones
    repeat i from 0 to 4
       sendTone(50+2*i)
       delay(3000)
       noTone
       delay(3000)

    delay(12000)

PUB delay(ms)
  waitcnt(cnt + clkfreq/1000 * ms)

PUB sendCWstr(stringptr)
  repeat strsize(stringptr)
      sendCWchr(byte[stringptr++])

PUB sendCWchr(char)    'A lookup Table of CW character

  case char
   " ":
    noTone
    delay(700)
    return

   "A", "a":
    dot
    dash
   "B", "b":
    dash
    dot
    dot
    dot
   "C", "c":
    dash
    dot
    dash
    dot

    . . . .

   "9":
    dash
    dash
    dash
    dash
    dot
   "0":
    dash
    dash
    dash
    dash
    dash

   "@":
    dot
    dash
    dash
    dot
    dash
    dot

  noTone
  delay(300)   ' Delay between each character

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

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


PRI dot
    sendTone(50)
    delay(100)
    noTone
    delay(100)


PRI dash
    sendTone(50)
    delay(300)
    noTone
    delay(100)



Here is the supplied Libaray


PUB Synth(CTR_AB, Pin, Freq) | s, d, ctr, frq

  Freq := Freq #> 0 <# 128_000_000     'limit frequency range
  
  if Freq < 500_000                    'if 0 to 499_999 Hz,
    ctr := constant(100 << 26)      '..set NCO mode
    s := 1                             '..shift = 1
  else                                 'if 500_000 to 128_000_000 Hz,
    ctr := constant(010 << 26)      '..set PLL mode
    d := >|((Freq - 1) / 1_000_000)    'determine PLLDIV
    s := 4 - d                         'determine shift
    ctr |= d << 23                     'set PLLDIV
    
  frq := fraction(Freq, CLKFREQ, s)    'Compute FRQA/FRQB value
  ctr |= Pin                           'set PINA to complete CTRA/CTRB value

  if CTR_AB == "A"
     CTRA := ctr                        'set CTRA
     FRQA := frq                        'set FRQA                   
     DIRA[Pin]~~                        'make pin output
     
  if CTR_AB == "B"
     CTRB := ctr                        'set CTRB
     FRQB := frq                        'set FRQB                   
     DIRA[Pin]~~                        'make pin output

PRI fraction(a, b, shift) : f

  if shift > 0                         'if shift, pre-shift a or b left
    a <<= shift                        'to maintain significant bits while 
  if shift < 0                         'insuring proper result
    b <<= -shift
 
  repeat 32                            'perform long division of a/b
    f <<= 1
    if a => b
      a -= b
      f++           
    a <<= 1


This 30m Beacon is running on; a Parallax Propeller, a 9Volt Battery, and two short 3 inch wires for the antenna.

--

2 comments:

Julian Moss said...

Thanks for publishing the listing, Eldon. Makes more sense to me than the assembler or C listings for the PIC stuff I've got. I've just gone and ordered myself one of these Gadget Gangsters!

Eldon R. Brown SR said...

Thanks Julian, but the code as publish is not all that well written, it was cobbled together from bits and pieces from other examples during the excitement of getting something to work. I have not decoded the results on a receiver via QRSS yet, and still hoping that processor PLL phase noise it not objectionable. I hope you find the Propeller a good distraction from your other life issues. Good luck my Friend.