Shop OBEX P1 Docs P2 Docs Learn Events
Absolute Prop NEWB, trying to simultaneously toggle GPIO, having trouble — Parallax Forums

Absolute Prop NEWB, trying to simultaneously toggle GPIO, having trouble

nmz787nmz787 Posts: 24
edited 2012-01-07 00:45 in Propeller 1
As best I can figure is that either I'm not setting my code structure correctly, or a cog can't access a register simultaneously... here's my code:
con
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000


pub main
cognew(@masterClock, 0)
cognew(@masterClock1, 0)


dat
        org      0                      'start of the program storage locations
masterClock
        or      dira,   masterClockPin            'pin now sets lines 0 and 1 as outputs
        :loop  
              xor      outa,   masterClockPin             'sets output 0 on and 1 off
              jmp      #:loop                 'go back and loop.


masterClock1
        or      dira,   shPin            'pin now sets lines 0 and 1 as outputs
        :loop1
              xor      outa,   shPin             'sets output 0 on and 1 off
              jmp      #:loop1                'go back and loop.


masterClockPin          long 1<<8          
shPin                   long 1<<9

I've even tried doing the PIN MUXing all in the first cog, but that doesn't help :/

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-01-06 23:49
    Each cog image (usually) needs to start with its own org directive (all address references are based on this). Which also means that all variables have to stay in the same org block (i.e. while you can refer to a label in a different org block, it doesn't usually match your cog image). Try this (untested):
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    pub main
    
      cognew(@masterClock, 0)
      cognew(@masterClock1, 0)
    
    dat             org     0
    
    masterClock     or      dira, masterClockPin    'pin now sets lines 0 and 1 as outputs
    :loop           xor     outa, masterClockPin    'sets output 0 on and 1 off
                    jmp     #:loop                  'go back and loop.
    
    masterClockPin  long    1<<8               
    
                    fit
    
    dat             org     0
    
    masterClock1    or      dira, shPin             'pin now sets lines 0 and 1 as outputs
    :loop           xor     outa, shPin             'sets output 0 on and 1 off
                    jmp     #:loop                  'go back and loop.
    
    shPin           long    1<<9
    
                    fit
                    
    DAT
    
    Local labels (starting with a colon) can be reused provided there is a global label in between.
  • nmz787nmz787 Posts: 24
    edited 2012-01-07 00:01
    It works (Thanks for the quick response!), though the toggled lines are slightly out of sync... I tried adding NOP before the loop starts in one of the "routines" (I haven't read the manual yet, so I don't know all the terminology), while that did move the phase, it was moved by ~42ns, not the 12.5ns I would expect if the chip is running at 80MHz

    BTW the period of the toggled GPIO is about 6MHz... (I have a 6MHz crystal connected, so maybe my setup is incorrect?)
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-07 00:10
    nmz787 wrote: »
    I tried adding NOP before the loop starts in one of the "routines" (I haven't read the manual yet, so I don't know all the terminology), while that did move the phase, it was moved by ~42ns, not the 12.5ns I would expect if the chip is running at 80MHz

    BTW the period of the toggled GPIO is about 6MHz... (I have a 6MHz crystal connected, so maybe my setup is incorrect?)
    If you have a 6MHz crystal connected then you should use _xinfreq = 6_000_000 which means your chip runs at 96MHz (with PLL16X). The wave period is 16 cycles (you toggle every 8 clocks) which means it's 96MHz/16 = 6MHz.

    For synchronisation there are several different ways of doing it. The most commonly used one is waitcnt. Meaning both cogs are given a cnt target in the future and sync on that.
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = [COLOR="orange"]6_000_000[/COLOR]
    
    var
      long  sync
    
    pub main
    
      [COLOR="blue"]sync := cnt + clkfreq                         '1 sec in advance[/COLOR]
      cognew(@masterClock,  @sync)
      cognew(@masterClock1, @sync)
    
    dat             org     0
    
    masterClock     [COLOR="blue"]rdlong  tmp1, par               'get sync target
                    waitcnt tmp1, #0[/COLOR]
                    
                    or      dira, masterClockPin    'pin now sets lines 0 and 1 as outputs
    :loop           xor     outa, masterClockPin    'sets output 0 on and 1 off
                    jmp     #:loop                  'go back and loop.
    
    masterClockPin  long    1<<8
    [COLOR="blue"]tmp1            res     1[/COLOR]
    
                    fit
    
    dat             org     0
    
    masterClock1    [COLOR="blue"]rdlong  tmp2, par               'get sync target
                    waitcnt tmp2, #0[/COLOR]
    
                    or      dira, shPin             'pin now sets lines 0 and 1 as outputs
    :loop           xor     outa, shPin             'sets output 0 on and 1 off
                    jmp     #:loop                  'go back and loop.
    
    shPin           long    1<<9
    [COLOR="blue"]tmp2            res     1[/COLOR]
    
                    fit
                    
    DAT
    
    The ~42ns do originate from the nop which takes 4 cycles at 1/96MHz = 10.416ns (total 41.6ns).
  • nmz787nmz787 Posts: 24
    edited 2012-01-07 00:27
    Thanks so much for your help... I will definitely start reading the manual!

    I was trying to do something very similar to this with an Atmega, and made no progress for the last 3 days trying to use interrupts (what I really need is a toggle 100-1000ns before the other GPIO toggles) and I was failing. I bet I could accomplish what I want with the Atmega, but I'm really a biologist developing some lab equipment, so the less time I spend on electronics, the more time I have actually developing the equipment I want!

    Thanks again! I'm already happy with the Propeller and this forum!
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-07 00:33
    nmz787 wrote: »
    ... what I really need is a toggle 100-1000ns before the other GPIO toggles
    In this case you could give both cogs a slightly different sync target (sync1/sync2) which is e.g. 20 cycles apart (equivalent to ~208ns).
    sync1 := cnt + clkfreq
      sync2 := sync1 + 20
      cognew(@masterClock,  @sync1)
      cognew(@masterClock1, @sync2)
    
    Enjoy your stay here!
  • nmz787nmz787 Posts: 24
    edited 2012-01-07 00:45
    kuroneko wrote: »
    In this case you could give both cogs a slightly different sync target (sync1/sync2) which is e.g. 20 cycles apart (equivalent to ~208ns).
    sync1 := cnt + clkfreq
      sync2 := sync1 + 20
      cognew(@masterClock,  @sync1)
      cognew(@masterClock1, @sync2)
    
    Enjoy your stay here!

    Thanks again!

    I actually don't need to toggle the second line all the time, but when I do toggle the second it needs to be synchronized (like I said 100-1000ns before the clock goes low). I am controlling a CCD, and one GPIO line needs to go low for 1 period of the constantly toggled GPIO line. This begins the readout of the CCD, it looks like this in ASCII art:

    _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_.......

    ¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯.......
Sign In or Register to comment.