Shop OBEX P1 Docs P2 Docs Learn Events
Help with counters needed — Parallax Forums

Help with counters needed

DRMorrisonDRMorrison Posts: 81
edited 2012-01-15 20:06 in Propeller 1
Hello, :smile:
I've done some programming with SPIN and am working on a project and need some help. I don't know much about how to use the counters
that are available. I understand that there are two, and that they can use two pins to detect or send a signal.
Of all of the things listed that it can do in the Prop. manual, I'm looking to count pulses. I've tried to decipher the counter mode in table, 2-7 on
page 98, but just can't seem to grasp it.

Here is what I would like to do, maybe someone can help with the code details.
The parts in red are the trouble areas.

PRI Alarm_Monitor
Repeat
waitpeq(|< AlarmActive, |< AlarmActive, 0)
set the pulse counter to 0
waitcnt(clkfreq*2 + cnt) ' wait ~ 2 seconds
if pulse counter > 0 ' pulses were counted, so change Mode
Mode := 1

If no pulses were counted, the loop simply repeats, waiting for the pin to go high. This runs in a separate cog by itself waiting for the AlarmActive pin to go high.

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-01-15 18:16
    This assumes you have a different pin for the pulse input, otherwise set it to AlarmActive instead.
    PRI Alarm_Monitor 
    
      ctra := constant(%0_01010_000 << 23 | pulse_pin)      ' detect positive edges
      frqa := 1
      
      repeat
        waitpeq(|< AlarmActive, |< AlarmActive, 0)
        [COLOR="orange"]phsa := 0[/COLOR]
        waitcnt(clkfreq*2 + cnt)
        [COLOR="orange"]if phsa <> 0[/COLOR]
          Mode := 1
    
    When you post code please wrap it in [noparse]
    
    [/noparse] tags.                        
  • DRMorrisonDRMorrison Posts: 81
    edited 2012-01-15 18:51
    Thank you for the reply. Sorry about the loose code.

    The AlarmActive is one pin, and the pulses would be counted on another pin only if AlarmActive went high. No need to count them until then.

    So the pulse_pin you show above would be that second pin? Do I need to set it as an input?
    Also, does this code start counting as soon as the ctra := constant(%0_01010_000 << 23 | pulse_pin) is called?
    Or can I wait until after the waitpeq has sensed a logic high?

    Thank you, Daniel
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-15 18:59
    DRMorrison wrote: »
    So the pulse_pin you show above would be that second pin? Do I need to set it as an input?
    Correct. Pin direction is set to input by default. So no action is required.
    DRMorrison wrote: »
    Also, does this code start counting as soon as the ctra := constant(%0_01010_000 << 23 | pulse_pin) is called?
    Or can I wait until after the waitpeq has sensed a logic high?
    Ynes[sic], this line enables the counter so it starts counting. But as frqa hasn't been set yet (default 0) it will only add 0. Once frqa is set to 1 (or any other non-null value) you will see change. So while the counter is armed, it doesn't really matter because you clear the accumulator (phsa) after you detect the high signal. Any (stray) accumulation until waitpeq is released will therefore be removed/ignored.
  • DRMorrisonDRMorrison Posts: 81
    edited 2012-01-15 19:13
    Thanks Kuroneko,
    That is very clear.
    I asked the second question because I was thinking about current draw, but not a deal breaker.

    I've been looking through my books and can't find much on how to code the ctra :=
    One instance shows ctra := %00100 << 26 as an example, and I can see how that moves everything over into the proper place.
    But the constant and | pulse_pin you gave are not shown anywhere. How do they work?

    Thank you, Daniel
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-15 19:27
    DRMorrison wrote: »
    But the constant and | pulse_pinyou gave are not shown anywhere. How do they work?
    SPIN is an interpreted language and the compiler is rather lazy in that all expressions are translated as is. In this case I'd end up with the counter mode shifted by 23 then OR'd together with the pin number. Provided you declare pulse_pin as a constant (in CON section) you can force all this to be pre-calculated as a single constant, e.g. ctra := $28000018 (POSEDGE on pin 24). It's mainly done for size/speed reasons although probably not that important in your case. That's what constant() does (manual v1.2, page 91). The | pulse_pin simply ORs the pin into the 32bit register value (bitwise OR, manual page 165). Have a look at the data sheet, it shows the register layout for e.g. ctra (chapter 4.9.1). There you'll find the bit locations for mode and pins etc.

    Re: 23/26 shifts, yes the 5 mode bits start at location 26. That said, in assembler mode setup is usually done with a movi instruction which requires a value starting at 23. So just personal preference.
  • DRMorrisonDRMorrison Posts: 81
    edited 2012-01-15 19:44
    Got it,
    Thank you very much. I'm starting to get the hang of this stuff, and it's kinda fun too. :smile:
    I referenced the manual and it is much clearer now.

    Thanks again, Daniel
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-15 19:47
    You can be even more verbose:
    ctra[30..26] := %01010
      ctra[8..0]   := pulse_pin
    
    As for current draw, while I haven't measured it an active counter is most likely insignificant compared to the nearly shutdown cog (waitpeq basically suspends this particular core). So I wouldn't worry about this.
  • DRMorrisonDRMorrison Posts: 81
    edited 2012-01-15 20:06
    Yes, after seeing your last reply, I can see the placement of the mode and pin assignments in the control register.
    Thank you, Daniel
Sign In or Register to comment.