Shop OBEX P1 Docs P2 Docs Learn Events
how to setup a new cog? — Parallax Forums

how to setup a new cog?

purplemonkeypurplemonkey Posts: 89
edited 2012-08-18 13:21 in Propeller 1
if i wanted this program to run on two different cogs with two different frequencies on two different pins, how would i do it?

CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000

txpin = 16
freq1 = 500
freq2 = 1000
delta = 50000
txfreq = 92_500_000.0
freqb = round(txfreq * 4_294_967_296.0 / (16.0 * 80_000_000.0))

PUB main | numclks1, numclks2



dira := 1 << txpin

numclks1 := clkfreq / (2 * freq1)
numclks2 := clkfreq / (2 * freq2)

ctrb[30..26] := %00010
ctrb[25..23] := 7
ctrb[5..0] := 16

repeat

' Generate the first frequency for one-half second
repeat freq1 >> 1
frqb := freqb + delta
waitcnt(numclks1 + cnt)
frqb := freqb - delta
waitcnt(numclks1 + cnt)

' Generate the second frequency for one-half second
repeat freq2 >> 1
frqb := freqb + delta
waitcnt(numclks2 + cnt)
frqb := freqb - delta
waitcnt(numclks2 + cnt)

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-08-18 08:04
    You don't need two cogs to do what you want. Each cog has two identical counters, A and B, that operate independently. You set up one for the first frequency to output to one I/O pin, then you set up the second for the second frequency and I/O pin.

    The Propeller Education Kit Labs tutorial has several sections on using multiple cogs and on using the counters. You might have a look at it.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-08-18 08:24
    Also, this statement will not do what you think it will:
    freqb = round(txfreq * 4_294_967_296.0 / (16.0 * 80_000_000.0))
    

    Spin does not do floating-point calculations inline like that, [edit]except in constant expressions, which is what you have[/edit]. You have to make method calls to one of the floating-point objects for each operation.

    Finally,

    attachment.php?attachmentid=78421&d=1297987572

    -Phil
  • BitsBits Posts: 414
    edited 2012-08-18 08:35
    Phil,

    I was under the impression that the compiler would convert floating point calculations, just wont work at run time. He has it placed in the CON block so I see no reason it would not work.
  • Mike GreenMike Green Posts: 23,101
    edited 2012-08-18 09:27
    Bits, you're absolutely right. You can have floating point constant expressions in the CON block or within a CONST(...) expression and the compiler will compute the value of the expression, floating point and all, when it compiles the program
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 10:16
    This is a simple method I setup in my standard template for creating a specific frequency output on one of the counters. As Mike points out, you can call this method twice (once for ctra, once for ctrb) and you'll be set.
    pub set_freq(ctrx, freq, pin)
    
    '' Sets ctrx to freq on pin (NCO/SE mode)
    '' -- freq in hz
    
      freq := clkfreq / freq                                ' convert freq for NCO mode
      freq := ($8000_0000 / freq) << 1
    
      case ctrx
        "a", "A":
          ctra := ((%00100) << 26) | pin                    ' configure ctra for NCO on pin
          frqa := freq                                      ' set frequency
          dira[pin] := 1                                    ' make pin an output
    
        "b", "B":                         
          ctrb := ((%00100) << 26) | pin  
          frqb := freq                    
          dira[pin] := 1
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-08-18 10:38
    My bad. I had not noticed that the expression was in the CONstant section. I'm so used to defining my constants in ALL_CAPS that I immediately assume that anything else is a variable.

    And, Bits, I's so glad you're feeling well enough to correct me! :)

    -Phil
  • purplemonkeypurplemonkey Posts: 89
    edited 2012-08-18 11:15
    JonnyMac wrote: »
    This is a simple method I setup in my standard template for creating a specific frequency output on one of the counters. As Mike points out, you can call this method twice (once for ctra, once for ctrb) and you'll be set.
    pub set_freq(ctrx, freq, pin)
    
    '' Sets ctrx to freq on pin (NCO/SE mode)
    '' -- freq in hz
    
      freq := clkfreq / freq                                ' convert freq for NCO mode
      freq := ($8000_0000 / freq) << 1
    
      case ctrx
        "a", "A":
          ctra := ((%00100) << 26) | pin                    ' configure ctra for NCO on pin
          frqa := freq                                      ' set frequency
          dira[pin] := 1                                    ' make pin an output
    
        "b", "B":                         
          ctrb := ((%00100) << 26) | pin  
          frqb := freq                    
          dira[pin] := 1
    

    Looks like both frequencies are the same and going to the same pin, or is that just because it's a template
  • purplemonkeypurplemonkey Posts: 89
    edited 2012-08-18 11:23
    I thought it would be as simple as creating variables one for the pin and one for the freq for each frequency and pin you wanted to broadcast on and then just call those values in pub main? With something like "new cog, freq, txpin2". So going back to the example you gave how do I call that second frequency? What would the syntax be?

    Incidentally if I were to have more frequencies that meant more cogs
    I've figured out to start a new cog with newcog,main@ stack command and long stack variable but how can I pass variables such as frequency and pin number with different values to different cogs? And don't you have to specify which cog?
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 12:19
    Keep in mind that's a method call that expects the counter (as a letter), the frequency output for the counter, and the pin number for that counter. Let's say you wanted P0 to run at 5Hz and P1 to run a 20Hz. You could do this:
    set_freq("A", 5, 0)
      set_freq("B", 20, 1)
    


    Easy as Pi. :)

    Since the counters run on their own they will stay at the desired frequency until you change them. Which causes me to think that I should have a way of stopping a counter. If the freq is 0 or lower, this update should do it.
    pub set_freq(ctrx, freq, pin)
    
    '' Sets ctrx to freq on pin (NCO/SE mode)
    '' -- freq in hz
    '' -- use freq of 0 to stop counter that is running
    
      if (freq > 0)
        freq := clkfreq / freq                              ' convert freq for NCO mode
        freq := ($8000_0000 / freq) << 1
        case ctrx
          "a", "A":
            ctra := ((%00100) << 26) | pin                  ' configure ctra for NCO on pin
            frqa := freq                                    ' set frequency
            dira[pin] := 1                                  ' make pin an output
         
          "b", "B":                         
            ctrb := ((%00100) << 26) | pin  
            frqb := freq                    
            dira[pin] := 1
    
      else
        case ctrx
          "a", "A":
            ctra := 0                                       ' disable counter
            outa[pin] := 0                                  ' clear pin/driver 
            dira[pin] := 0                                  
         
          "b", "B":                         
            ctrb := 0 
            outa[pin] := 0  
            dira[pin] := 0
    
  • purplemonkeypurplemonkey Posts: 89
    edited 2012-08-18 12:52
    Thats cool thanks!

    if i want 2 fm frequencies each on two cogs so in total 4 frequencies how would i do that?

    would i just do

    newcog,Pub???@stack

    set_freq("A", 48, 0) set_freq("B", 100, 1)

    then just repeat this for each cog?
    how do i specify which cog to run which frequencies on?


    bit lost sorry, real newbie!
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 12:54
    Here's a possible (tested, it works) solution for running counters outside the main cog. Note that with this strategy you cannot change the frequency on-the-fly, you have to stop and restart the cog. It would be possible to write a proper object that let you change the frequency. I'll leave that to you.
    pri freqout_2x(p1, f1, p2, f2, killpntr)                ' launch with cognew()
    
    '' Run one or both counters in NCO mode
    '' -- designed to run in background cog
    
      if (p1 => 0)                                          ' output on this pin?
        ctra := ((%00100) << 26) | p1                       ' set counter for NCO on this pin (p1)
        frqa := ($8000_0000 / (clkfreq / f1)) << 1          ' set frqx for frequency (f1)
        dira[p1] := 1                                       ' set pin to output mode
    
      if (p2 => 0)
        ctrb := ((%00100) << 26) | p2 
        frqb := ($8000_0000 / (clkfreq / f2)) << 1
        dira[p2] := 1  
    
      long[killpntr] := false                               ' let cog run after setup
      repeat
      
        { let counter(s) run }
        
      until(long[killpntr])
    
      cogstop(cogid)                                        ' kill this cog
    


    Here's how I called it with my test:
    cognew(freqout_2x(0, 5, 15, 5, @stopblinks), @stack)
      pause(5000)
      stopblinks := true
    


    In the test pins P0 and P15 output 5Hz for five seconds, then I kill the cog by setting stopblinks to true. Note that for this I use the pin first, then the frequency (will probably change my set_freq() to this as well).
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 13:03
    Are you trying to run 92.5MHz? I don't think you can do that in NCO mode. Have a look a Synth.spin in the Propeller Library on your system.
  • purplemonkeypurplemonkey Posts: 89
    edited 2012-08-18 13:03
    sorry really confused what's going on here??? I'm real newbie i'm afraid just a couple of weeks in....
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 13:09
    Well, to be honest, you may not be ready for what you want to do. I'm a casual jogger -- have a long way to go before I'm ready for a marathon.

    The worst thing you can do (in my opinion) is try to get ahead of yourself. It would probably do you a lot of good to read and work through the Propeller Education Kit manual; you can find it under the Help menu in the Propeller Tool.
  • purplemonkeypurplemonkey Posts: 89
    edited 2012-08-18 13:17
    Ok thanks, just one question though what is the difference between this method and synth frequency?
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-08-18 13:21
    When you read the Synth code you'll see that it uses PLL mode for frequencies 500KHz and higher.
Sign In or Register to comment.