Shop OBEX P1 Docs P2 Docs Learn Events
Limit of 8 nested blocks exceeded? — Parallax Forums

Limit of 8 nested blocks exceeded?

turbosupraturbosupra Posts: 1,088
edited 2010-06-22 19:50 in Propeller 1
I'm sure there is a more efficient way (and far better way) to code this, but I'm not Hano (I'm very new to this) and so I'm wondering what the purpose of this 8 nested blocks limit is for?

Here is my loop, thoughts?



repeat
           
          repeat
           
            Debug.Str(string("     Waiting to enter repeat loop",13)) 
           
                   firstloopcnt := cnt 
            if ina[noparse][[/noparse]PulseInputPin] == 1
                   timeoffirstpulse := cnt '(cnt/1000)                                              ' 90
                   Debug.Str(string("1st if PulseInputPin == 1 true",13))
                   Debug.Str(string("timeoffirstpulse := cnt value is:"))
                   Debug.Dec(||timeoffirstpulse)
                   Debug.Tx(13)
                   Debug.Tx(13)
                   'Debug.Str(string("About to hit the 40 million hz waitcnt in 1st loop",13))
                   'waitcnt(ClkFreq/2 + cnt)
                   secondloopcnt := cnt
                   lowhigh1_detected := true
           
                        if ina[noparse][[/noparse]PulseInputPin] == 0 AND lowhigh1_detected == true
                            highlow1_detected := true
                            Debug.Str(string("lowhigh1_detected and highlow1_detected, entering 2nd loop",13))               
                                        repeat
                                              if ina[noparse][[/noparse]PulseInputPin] == 1 AND highlow1_detected == true
                                                     timeofsecondpulse := cnt '(cnt/1000)                                              ' 90
                                                     Debug.Str(string("2nd if PulseInputPin == 1 true",13))
                                                     Debug.Str(string("timeofsecondpulse := cnt value is:"))
                                                     Debug.Dec(||timeofsecondpulse)
                                                     Debug.Tx(13)
                                                     Debug.Tx(13)
                                                     'Debug.Str(string("About to hit the 40 million hz waitcnt in 2nd loop",13))
                                                     'waitcnt(ClkFreq/2 + cnt)
                                                     thirdloopcnt := cnt
                                                     lowhigh2_detected := true
                                                 
                                                  if ina[noparse][[/noparse]PulseInputPin] == 0 AND lowhigh2_detected == true
                                                     highlow2_detected := true
                                                     Debug.Str(string("highlow2_detected, entering 3nd loop",13))
                                                     
                                               
                                                      repeat
                                                            if ina[noparse][[/noparse]PulseInputPin] == 1 AND highlow2_detected == true
                                                                    timeoffirstpulse := cnt '(cnt/1000)                                              ' 90
                                                                    Debug.Str(string("3rd if PulseInputPin == 1 true",13))
                                                                    Debug.Str(string("timeofsecondpulse := cnt value is:"))
                                                                    Debug.Dec(||timeofsecondpulse)
                                                                    Debug.Tx(13)
                                                                    Debug.Tx(13)
                                                                    'Debug.Str(string("About to hit the 40 million hz waitcnt in 3rd loop",13))
                                                                    'waitcnt(ClkFreq/2 + cnt)
                                                                    Debug.Str(string("Outputting to pin",13))
                                                                    outa[noparse][[/noparse]OutPutPin] := 1
                                                                    WaitCnt((ClkFreq / 1000 * fullsec_wait) * 2 + cnt) ' leave output pin set to high for a full second
                                                                    Debug.Str(string("Done outputting to pin",13))
                                                                    outa[noparse][[/noparse]OutPutPin] := 0                                 
                                                                    quit
                                                              
                                                                    
                                                            elseif thirdloopcnt =< (- 120_000_000 + cnt)
                                                                    Debug.Str(string("3rd loop timeout, quitting",13))
                                                                    'waitcnt(ClkFreq/2 + cnt)                         
                                                                    quit 
                                         
                                         
                                         
                                         
                                                     
                                              elseif secondloopcnt =< (- 120_000_000 + cnt)
                                                     lowhigh2_detected := false
                                                     Debug.Str(string("2nd loop timeout, quitting",13))
                                                     'waitcnt(ClkFreq/2 + cnt)                         
                                                     quit 
                                         
           
           
           
            elseif firstloopcnt =< (- 120_000_000 + cnt)
                   lowhigh1_detected := false
                   Debug.Str(string("1st loop timeout, quitting",13))
                   'waitcnt(ClkFreq/2 + cnt)  
                   next ' **wanted to change this to quit**
           

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-21 15:41
    I'd just move the innermost REPEAT into its own method.

    The limit on nesting has to do with some table inside the compiler that was arbitrarily limited to 8 entries when the compiler was designed. For REPEATs and IFs, there has to be some information kept around so internal labels and other related stuff can be kept around while the code is being generated.

    It's usually clearer programming to keep nesting to 3 or 4 levels and moving deeper stuff into subroutines. The additional call overhead is pretty low at that point.
  • heaterheater Posts: 3,370
    edited 2010-06-21 15:45
    turbosupra: "...wondering what the purpose of this 8 nested blocks limit is for?"

    I think your code example answers that question nicely. As you see after a few levels of indentation it becomes very hard to tell what the hell is going on in the code.

    Some would say the language, Spin in the case, should not impose arbitrary limits on such things.
    I'm happy enough with a depth of 8 especially as Spin has no braces or block end markers it soon
    becomes hard to see the form of the code.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-21 15:49
    Even with BEGIN / END pairs or { / } brackets, it's hard to keep track of nesting much beyond 3 or 4 levels. In fact, you have to use indentation to help with this even if you have explicit brackets.
  • heaterheater Posts: 3,370
    edited 2010-06-21 16:07
    True enough Mike. But at least you can run the thing through a pretty printer and fix up the indentation.

    The opening example has indentation all over the place making it hard to see the original intent (not indent).
    Perhaps that's how it was written, perhaps it got mangled as it is made it way to this web page. Impossible to tell.

    Still let's not have yet another "white space block delimiter or not" debate.
    As you say the issue here is the same regardless.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • jazzedjazzed Posts: 11,803
    edited 2010-06-21 21:14
    Just use curly braces [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Pages: Propeller JVM
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-21 23:41
    So like I've changed it to below (I'm new at this, hence the simplistic question)

    If so, is there any issue with the variables inside of the Main method being read by the Sigout method? I assume there is not because they are not defined as local, but I wanted to make sure



    Mike Green said...
    I'd just move the innermost REPEAT into its own method.

    The limit on nesting has to do with some table inside the compiler that was arbitrarily limited to 8 entries when the compiler was designed. For REPEATs and IFs, there has to be some information kept around so internal labels and other related stuff can be kept around while the code is being generated.

    It's usually clearer programming to keep nesting to 3 or 4 levels and moving deeper stuff into subroutines. The additional call overhead is pretty low at that point.



    repeat
               
              repeat
               
                Debug.Str(string("     Waiting to enter repeat loop",13)) 
               
                       firstloopcnt := cnt 
                if ina[noparse][[/noparse]PulseInputPin] == 1
                       timeoffirstpulse := cnt '(cnt/1000)                                              ' 90
                       Debug.Str(string("1st if PulseInputPin == 1 true",13))
                       Debug.Str(string("timeoffirstpulse := cnt value is:"))
                       Debug.Dec(||timeoffirstpulse)
                       Debug.Tx(13)
                       Debug.Tx(13)
                       'Debug.Str(string("About to hit the 40 million hz waitcnt in 1st loop",13))
                       'waitcnt(ClkFreq/2 + cnt)
                       secondloopcnt := cnt
                       lowhigh1_detected := true
               
                            if ina[noparse][[/noparse]PulseInputPin] == 0 AND lowhigh1_detected == true
                                highlow1_detected := true
                                Debug.Str(string("lowhigh1_detected and highlow1_detected, entering 2nd loop",13))               
                                            repeat
                                                  if ina[noparse][[/noparse]PulseInputPin] == 1 AND highlow1_detected == true
                                                         timeofsecondpulse := cnt '(cnt/1000)                                              ' 90
                                                         Debug.Str(string("2nd if PulseInputPin == 1 true",13))
                                                         Debug.Str(string("timeofsecondpulse := cnt value is:"))
                                                         Debug.Dec(||timeofsecondpulse)
                                                         Debug.Tx(13)
                                                         Debug.Tx(13)
                                                         'Debug.Str(string("About to hit the 40 million hz waitcnt in 2nd loop",13))
                                                         'waitcnt(ClkFreq/2 + cnt)
                                                         thirdloopcnt := cnt
                                                         lowhigh2_detected := true
                                                     
                                                             if ina[noparse][[/noparse]PulseInputPin] == 0 AND lowhigh2_detected == true
                                                                highlow2_detected := true
                                                                Debug.Str(string("highlow2_detected, entering 3nd loop",13))
                                                                Sigout
                                             
                                                         
                                                  elseif secondloopcnt =< (- 120_000_000 + cnt)
                                                         lowhigh2_detected := false
                                                         Debug.Str(string("2nd loop timeout, quitting",13))
                                                         'waitcnt(ClkFreq/2 + cnt)                         
                                                         quit 
                                             
               
               
               
                elseif firstloopcnt =< (- 120_000_000 + cnt)
                       lowhigh1_detected := false
                       Debug.Str(string("1st loop timeout, quitting",13))
                       'waitcnt(ClkFreq/2 + cnt)  
                       next ' **wanted to change this to quit**
               
    
    
    
    
    
    Pub Sigout
    
    
             
             repeat
                  if ina[noparse][[/noparse]PulseInputPin] == 1 AND highlow2_detected == true
                        timeoffirstpulse := cnt '(cnt/1000)                                              ' 90
                        Debug.Str(string("3rd if PulseInputPin == 1 true",13))
                        Debug.Str(string("timeofsecondpulse := cnt value is:"))
                        Debug.Dec(||timeofsecondpulse)
                        Debug.Tx(13)
                        Debug.Tx(13)
                        'Debug.Str(string("About to hit the 40 million hz waitcnt in 3rd loop",13))
                        'waitcnt(ClkFreq/2 + cnt)
                        Debug.Str(string("Outputting to pin",13))
                        outa[noparse][[/noparse]OutPutPin] := 1
                        WaitCnt((ClkFreq / 1000 * fullsec_wait) * 2 + cnt) ' leave output pin set to high for a full second
                        Debug.Str(string("Done outputting to pin",13))
                        outa[noparse][[/noparse]OutPutPin] := 0                                 
                        quit
                                                                  
                                                                        
                  elseif thirdloopcnt =< (- 120_000_000 + cnt)
                       Debug.Str(string("3rd loop timeout, quitting",13))
                       'waitcnt(ClkFreq/2 + cnt)                         
                       quit 
                                             
    
    
    
    
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-22 16:33
    What's the purpose of this code?

    I think it can be done without that kind of indentation, but then we need to better understand what you want the program to do.

    My first feeling is, that you only need one repeat loop and the if statements when you introduce a variable which tells you what cycle number you have reached.
    Maybe it would be good to use the waitpne and waitpeq instructions to increase accuracy?

    What max. and min. pulse/pause times do you expect?
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-22 16:59
    The purpose of this code is to monitor the number of pulses per time period, and output a signal if the number of pulses exceeds a preset number in a certain time period



    The indents are just the way the IDE did that when I hit the tab button?

    I may be able to get away with one repeat loop, but I want the loop to continuously poll (and not pause) which is why I put more than one loop in.

    The max time period would be 3 seconds, with at least 1 pulse per second.



    I'm really new to spin code and would love to see your logic in how you would code this, if you care to write up an example real quick?
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-22 19:50
    That sound pretty much like it's a perfect job for a counter.

    Then the program looks like:
    1. setup the counter to count impulses

    repeat
    2. clear the counter
    3. wait or do something usefull for the period
    4. check the result and do whatever you want based on the result

    For setting up counters you can have a look at the following parallax lab:
    http://www.parallax.com/Portals/0/Downloads/appnt/prop/AN001-PropellerCountersv1.2.zip

    Post Edited (MagIO2) : 6/22/2010 7:55:18 PM GMT
Sign In or Register to comment.