Shop OBEX P1 Docs P2 Docs Learn Events
PROGRAMMING HELP — Parallax Forums

PROGRAMMING HELP

I have recently started learning about the Propeller through the Programming and Customizing the Multicore Propeller Microcontroller Book. I require help on the "repeat count * 2" portion of the listed program:

PUB Main

LED_Flash(0, 30, 5) 'Flash led
LED_Flash(4, 15, 15) 'Then another
LED_Flash(7, 7, 26) 'And finally a third


PUB LED_Flash(Pin, Duration, Count)
{Flash led on Pin for Duration a total of Count times.
Duration is in 1/100th second units.}

Duration := clkfreq / 100 * Duration 'Calculate cycle duration
dira[0..7]~~ 'Set pins to output

repeat Count * 2 'Loop Count * 2 times
!outa[pin] 'Toggle I/O Pin
waitcnt(Duration + cnt) 'Delay for some time

Looking at it I assumed that regardless of the value in the count parameter it would double the number of flashes(repeat Count * 2). When it worked as it should, confusion and curiosity set in. To save space only the first LED_Flash line of code will be referenced. [LED_Flash(0, 30, 5). In repeat Count * 2, values were changed with the following results:

A value of 1 - led flashed 3 times
A value of 3 - led flashed 8 times
A value of 4 - led flashed 10 times

I still cannot understand exactly what is happening and I don't want to move on hoping it would come to me later.

Need some help.

Thanks

Comments

  • It's hard to figure out what you're actually doing. Please use the [ code] and [ /code] markers (without the space after the "[") to quote your code along with the indenting spaces that should be there. Also show the actual code you're referencing. What you've shown above (if properly indented) should flash the LED the number of times specified in Count. One count applies to the off state and one count applies to the on state ... that's why the "* 2". The I/O pin is toggled (off -> on and on -> off) each count.
  • And how can we tell if the issue isn't with the code calling LED_Flash anyway?
  • JonnyMacJonnyMac Posts: 9,105
    edited 2015-12-17 20:21
    I'm of the opinion that good code is obvious code, and there's nothing very obvious for a beginner about that method. Here's how I would write it.
    pub led_flash(pin, duration, count)
    
      dira[pin] := 1                                                 ' make pin an output
    
      duration *= clkfreq / 100                                      ' convert duration to system ticks
    
      repeat count                                                   ' run the loop
        outa[pin] := 1                                               ' led on
        waitcnt(cnt + duration)                                      ' wait
        outa[pin] := 0                                               ' led off
        waitcnt(cnt + duration)                                      ' wait
    
    It takes a few extra lines, but it's easier to follow. Once this is understood it can be condensed using toggling. Better to start with verbose code, in my opinion.

    Once that's understood, you could go to this:
    pub led_flash(pin, duration, count)
    
      dira[pin] := 1                                                 ' make pin an output
    
      duration *= clkfreq / 100                                      ' convert duration to system ticks
    
      repeat (count * 2 #> 0)                                        ' run the loop (2x for on & off via toggle)
        !outa[pin]                                                   ' toggle led
        waitcnt(cnt + duration)                                      ' wait
    

    The advantage? It doesn't care about the default state of the LED. You might have an LED that is already on when calling this version -- it will flash off count times, then go back to on. I also added a little error trap so the code doesn't run when a negative count is passed. This is usually not necessary, but some situations will want to be protected from bad input.

    And here's what you might finally work up to. Yes, a little overbearing for an LED flasher, but for some kind of industrial process control, the limits could be beneficial.
    pub cycle_output(pin, duration, count)
    
      if ((pin < 0) or (pin > 27))                                   ' validate pin
        return                                                       '  abort if bad
      dira[pin] := 1                                                 ' make pin an output
      
      duration := 1 #> duration <# 100                               ' limit timing to 10ms to 1s
      duration *= clkfreq / 100                                      ' convert duration to system ticks    
    
      if (count < 0)                                                 ' validate count
        return                                                       '  abort if negative
      count <#= 10                                                   ' limit cycles 
    
      repeat count * 2
        !outa[pin]                                                   ' toggle output
        waitcnt(cnt + duration)                                      ' wait
    

    I was explaining to a friend in a Hollywood prop shop that coding is like sculpting: we rough things out for form, then refine and refine and refine until we're at our elegant best.
  • Thank you guys so much. I completely understand now. Once again THANKS!!!
  • Heater.Heater. Posts: 21,230
    "Sculpting". A fine analogy.

    But mostly it's like building house out of cards. If, after a lot of careful perseverance, you manage to get it to stand up ship it and hope nobody breaths on it.

    Next week your customer is back asking for a basement and 10 new floors to be added to it !

  • Cluso99Cluso99 Posts: 18,069
    Jon,
    Your code is easy to understand!

    I agree, this is the type of code that beginners should be exposed to. It is much easier to understand advancing the code to show how it can be simplified - in your case using XOR.

    There are less questions, and the beginner feels like they have accomplished something by understanding it on their own.
  • Gosh dar... @JonnyMac you did it again.

    This

    repeat (count * 2 #> 0)

    is so obvious, once you showed it to me. I am bowing deep to the master.

    I am reading a lot of your source code, because somehow a lot of the OBEX stuff I use for playing around was written by you.

    I really like the way you code things, and comment them.

    Just trying to learn, all the time.

    Thank you for all your contributions here and them books and articles you wrote.

    Mike
  • JonnyMacJonnyMac Posts: 9,105
    edited 2015-12-20 16:00
    This

    repeat (count * 2 #> 0)

    is so obvious, once you showed it to me. I am bowing deep to the master.
    For the record, I had seen that in another program and adopted it. One of my favorite ways to limit values is like this:
      value := LO_LIMIT #> value <# HI_LIMIT
    
    ...which I used above. To me it just shouts, "The value is forced between the low and high limits." This can also be used as a control expression for a repeat loop. I add parenthesis when using an expression as the control value for a repeat loop for clarity.

    We don't have to be the origin of all good ideas, we just need to recognize and adopt them. I think that's how we become masters, and that's why I visit the forums regularly -- there are always bits of masterful programming that I'm able to adopt and deploy.

    Thank you for your kind comments. I was telling a young actor friend, whom I'm mentoring with a Boe-Bot, that I believe my purpose is to help people with what I know and to entertain them (I choose acting for that). Luckily, that second skill helps me with the first!

    Cheers!
Sign In or Register to comment.