Shop OBEX P1 Docs P2 Docs Learn Events
Cog start delay time? — Parallax Forums

Cog start delay time?

TJHJTJHJ Posts: 243
edited 2008-04-13 01:31 in Propeller 1
So Ive been thinking about this. Not a good start usually, but if each cog is loaded w/ the complete 32k of ram, then there should be no additional time delay when starting a new cog other than the hub access time? Is this correct?

So here is why I ask this question.

In my ignition timing controller, I need two independent timers going. So time simple solution I am using now is one cog watch for TDC, then Starts a new cog each TDC timing from there. Once its timing is done it returns to the TDC marking cog, so at most I have 2 cogs running timers at once.



Pub TDC
  Dira[noparse][[/noparse]16]~~           

  
  
  dira[noparse][[/noparse]coilout]~~
  
  bs2.start(28,29)
 
    Repeat 
        Outa[noparse][[/noparse]16]~~        ' Check is running by 17 on
        Waitpne(|<Crankin, |< Crankin, 0) 'Wait for Low side of Crank sensor to Reset fire time 
        Waitpeq(|< Crankin, |< Crankin, 0)    'Wait for High side of crank sensor. TDC
                                             
        
        Cognew(Fire.Tdelay(Advance,Coilout), @stack7) ' start timing for next advance










It then calls this function.


Obj
BS2 : "BS2_Functions"



Pub Tdelay(Advance, Coilout)
       
        bs2.Pause_us((Advance))          '' Wait advance
        Outa[noparse][[/noparse]Coilout]~~ '' Make Pin high, Switch SCR to fire plug. 
        outa[noparse][[/noparse]10] := 1
        bs2.pause_us(5)  '' Allow time to fire
        Outa[noparse][[/noparse]Coilout]~ '' Turn off Pin... Recharge Cap
        outa[noparse][[/noparse]10] := 0






So probably not the most efficient way to do this, but Im learning as I go.

What I am concerned about is that there will be a delay caused by the cog start command, that I will need to compensate for in my timing. Eg It take 4 ms to start the new cog so I can subtract 4ms off the advance delay.

Any help is always appreciated.

Thank you for your time
TJ

Comments

  • AleAle Posts: 2,363
    edited 2008-04-12 19:39
    Starting a new cog only implies copying 2 kbytes. The cog only has 2 kbytes of RAM. In the case of a new cog for spin code the interpreter is loaded. The delay can be easily found saving the CNT before the COGnew and as first instruction in the new started routine. If you subtract the time for the cognew routine and the read of the CNT var... you get how long it took... around 512*16 cycles...
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-04-12 20:35
    As a matter of programming style, starting a new cog should not be viewed as a substitute for a method call. Why not start the cog and leave it running, then trigger the delay routine by setting a monitored hub location? You'll save the COGNEW overhead and a lot of unnecessary thrashing.

    -Phil
  • TJHJTJHJ Posts: 243
    edited 2008-04-13 00:28
    Well I seem to be having some issues making that work out, The method call.

    The only 3 wait commands I can find, Are WaitPNE/WaitPEQ, WaitCnt, And Waitvid. So I cant seem to find a good way to pause the cog, Maybe Im missing an obvious way to do this.

    So here is the best way I can seem to figure out how to do this, but it develops a odd loop system. I wish I could find a wait for var = or a wait for write at location.
    So this is the way I come up with do this.


    Pub TDC
      Dira[noparse][[/noparse]16]~~           
    
      
      
      dira[noparse][[/noparse]coilout]~~
      
      bs2.start(28,29)
      Cognew(Fire.Tdelay1(Advance,Coilout), @stack7) ' start timing for next advance
      Cognew(Fire.Tdelay2(Advance,Coilout), @stack8) ' start timing for next advance
        Repeat 
            
            Outa[noparse][[/noparse]16]~~        ' Check is running by 17 on
            
            Waitpne(|<Crankin, |< Crankin, 0) 'Wait for Low side of Crank sensor to Reset fire time 
            Waitpeq(|< Crankin, |< Crankin, 0)    'Wait for High side of crank sensor. TDC
            !Start 'alternating 1 or 0 values for the start var. 
                                
            
            
    
    
    
    
    




    Pub Tdelay1(Advance, Coilout)
         Repeat
            if Start == 1 
              bs2.Pause_us((Advance))          '' Wait advance
              Outa[noparse][[/noparse]Coilout]~~ '' Make Pin high, Switch SCR to fire plug. 
              outa[noparse][[/noparse]10] := 1
              bs2.pause_us(5)  '' Allow time to fire
              Outa[noparse][[/noparse]Coilout]~ '' Turn off Pin... Recharge Cap
              outa[noparse][[/noparse]10] := 0
    
    Pub Tdelay2(Advance, Coilout)
         Repeat
            if Start == 0 
              bs2.Pause_us((Advance))          '' Wait advance
              Outa[noparse][[/noparse]Coilout]~~ '' Make Pin high, Switch SCR to fire plug. 
              outa[noparse][[/noparse]10] := 1
              bs2.pause_us(5)  '' Allow time to fire
              Outa[noparse][[/noparse]Coilout]~ '' Turn off Pin... Recharge Cap
              outa[noparse][[/noparse]10] := 0
    
    
    


    But this seems so inefficient that it hurts me, and IM a bad coder.

    So then Ive got to ask does this work.

    If I call cog new w/ a method, Can I recall that method and have it run in the new cog?

    Eg

    Pub TDC
      Dira[noparse][[/noparse]16]~~           
    
      
      
      dira[noparse][[/noparse]coilout]~~
      
      bs2.start(28,29)
      Waitcog1 := Cognew(Fire.Tdelay(Advance,Coilout), @stack7) ' start timing for next advance
      Waitcog2 := Cognew(Fire.Tdelay(Advance,Coilout), @stack8) ' start timing for next advance
        Repeat 
            
            Outa[noparse][[/noparse]16]~~        ' Check is running by 17 on
            
            Waitpne(|<Crankin, |< Crankin, 0) 'Wait for Low side of Crank sensor to Reset fire time 
            Waitpeq(|< Crankin, |< Crankin, 0)    'Wait for High side of crank sensor. TDC
            !Spark
            if !Spark ==  1
               Cogstart(Waitcog1)
            else 
               Cogstart(Waitcog2)
    
    
    
    



    With the original code being called by Fire.Tdelay. No internal repeat.

    It seems smoother but maybe Im missing a fundamental way to do this, So any help is always appreciated. I am a self taught programmer, as proably is apparent by the in efficiency of my coding. So points always appreciated.

    Thanks again
    TJ


    Edit. Since a cog only has 2k of ram, What happens if you try to load a program greater than 2k? Does it just become much slower because its always having to wait for the hub to access part of its program. I have never thought about this before, never having programs that large, yet now I am approaching that limit quickly.

    Post Edited (TJHJ) : 4/13/2008 12:35:01 AM GMT
  • parskoparsko Posts: 501
    edited 2008-04-13 01:31
    TJHJ,

    I would suggest trying what PhiPi suggests. Dedicate a cog to do all this for you. AKA, start up a cog that listens to a pin (your crank trigger). This trigger should always happen at the same time, wrt the crank angle. This can be done using the onboard timers (timer A). You would probably program it to read a rising edge.

    This will run in this cog, in the background, as long as the prop has power, and the cog has not been stopped. You can start this at the beginning of "this cogs code". After you start it, you can have the remainder of "code in the cog" act upon the result of the timer, and loop endlessly. So, the rest of the code (after you've initiated your timer) will simply be a repeat loop. After the trigger is seen, the the loop begins, you execute your "advance" wait code, then fire the plug (remember, this all happens while the timer is sitting in the background looking at the crank trigger!!!).

    This is the beauty of the prop. 8 processors, each with two timers that can run completely independently of the code your are running in that particular cog (so, you could have a timer outputting a pulse width to your coffee maker while your code calculates PI to a billion places and displays it to a TV). Or a better analogy, you can monitor a crank trigger, while the code waits for that trigger and acts accordingly when it occurs.

    This will force you to learn the counters (I think I've been calling them timers nono.gif ) and will slow down your progress, but I think in the end you'll end up happier, with more resources available to drive your injectors (and coffee maker tongue.gif )

    Dig?

    -Parsko

    BTW - I believe a coginit happens in ~103us at 80MHz (see chips comments at http://forums.parallax.com/forums/default.aspx?f=25&m=132607 )
Sign In or Register to comment.