Shop OBEX P1 Docs P2 Docs Learn Events
Something's wrong ... and it's driving me crazy — Parallax Forums

Something's wrong ... and it's driving me crazy

tmaynardtmaynard Posts: 27
edited 2010-06-08 21:18 in Propeller 1
Here's a simple, little LED blinker. I've been over it a million times, I've tweaked it a thousand ways, but it flat doesn't work:
                        org     0
entry                       
                        or      dira, Pin               ' Select P4 for output (1)
                        andn    outa, Pin               ' Set P4 low (0)

                        mov     OnTime, OnDelay         ' Set up delays on/off
                        add     OnTime, cnt
                        
                        mov     OffTime, OffDelay
                        add     OffTime, cnt
:loop
                        xor     outa, Pin               ' Toggle pin
                        waitcnt OnTime, OnDelay         ' Pause 1/4 sec
                         
                        xor     outa, Pin               ' Toggle pin
                        waitcnt OffTime, OffDelay       ' Pause 3/4 sec
                      
                        jmp     #:loop


Pin                     long    |< 4

OnDelay                 long    80_000_000 / 4
OffDelay                long    (80_000_000 / 4) * 3

OnTime                  res     1
OffTime                 res     1

                        fit


It's supposed to blink at 1 Hz, with a 25% duty cycle. The behavior is just as if the second WAITCNT missed its "window". I get one quick flash, and then the LED stays on *forever* (well, you know how long), and then a quick flash, etc. I have tried:
  • Using the same initial value of CNT for both waits
  • Using a small immediate value (#24) instead of Delay on the first go
  • Using hard-coded Delays (20_ and 60_000_000)
  • Reordering the MOV/ADD
  • Grouping the MOV/ADD
  • etc.
PASD shows that it works, but of course PASD ignores WAITCNTs. Your insight is requested.

Tom.

[noparse][[/noparse]Edited to add that it works just fine if either WAITCNT is commented out, only when both are active does the problem appear.]

Comments

  • tonyp12tonyp12 Posts: 1,951
    edited 2010-06-08 19:08
    >waitcnt OffTime, OffDelay ' Pause 3/4 sec

    needs to be:
    waitcnt OnTime, OffDelay ' Pause 3/4 sec

    As waitcnt adds ondelay to the OnTime varible during the wait .
    As you use a new varible that is set to zero, it would take 58sec for the counter to roll over
  • KyeKye Posts: 2,200
    edited 2010-06-08 19:10
    You're missing the timing windows with that code.

    Do this instead:

                            org     0
    entry                       
                            or      dira, Pin               ' Select P4 for output (1)
                            andn    outa, Pin               ' Set P4 low (0)
    
                            mov     counter, OnDelay        ' Set up delays on/off
                            add     counter, cnt
    :loop
                            xor     outa, Pin               ' Toggle pin
                            waitcnt counter, OffDelay       ' Pause 1/4 sec
                             
                            xor     outa, Pin               ' Toggle pin
                            waitcnt counter, OnDelay        ' Pause 3/4 sec
                          
                            jmp     #:loop
    
    
    Pin                     long    |< 4
    
    OnDelay                 long    80_000_000 / 4
    OffDelay                long    (80_000_000 / 4) * 3
    
    
    Counter                 res     1
    
                            fit
    




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • HarpritHarprit Posts: 539
    edited 2010-06-08 19:12
    I don't see a clock freq spec.
    Harprit
  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-08 19:20
    The problem is that you're setting up the two times (OnTime and OffTime) starting at the same time. Your initial OnTime is (initialTime + 1/4 sec). Your initial OffTime is (initialTime + 8*12.5ns + 3/4 sec). It's better to do:
                            mov     OnTime,cnt
                            add      OnTime,OnDelay            ' End of on period is 1/4 second from now
                            mov     OffTime,OnTime
                            add      OffTime,OffDelay            ' End of off period is 3/4 second from end of on period
    


    You then want the WAITCNTs to move ahead 1 second each time through the loop like:
                            waitcnt  OnTime,OneSecond
    ... and
                            waitcnt  OffTime,OneSecond
    ... with
    OneSecond        long     80_000_000
    
  • tmaynardtmaynard Posts: 27
    edited 2010-06-08 19:56
    Harprit said...
    I don't see a clock freq spec.
    It's in the Spin section (not shown):
    CON
      _clkmode = xtal1 + pll16x                             ' Set clock for 80 MHz
      _xinfreq = 5_000_000
    
    PUB Start
      cognew(@entry, 0)
    
    

    Mike Green said...
    The problem is that you're setting up the two times (OnTime and OffTime) starting at the same time.
    That's true, but I'm adding dozens of millions of Delay cycle time, too. I was sure that I was missing the "window" -- but I just don't see how.

    I'll try all suggestions and report back.

    Thanks!
  • Mike GreenMike Green Posts: 23,101
    edited 2010-06-08 20:06
    You're adding 1/4 second to the OnTime time and 3/4 second to the OffTime time each pass through the loop. Eventually the 3/4 second delays will move the current time past that in OnTime and you'll have one of those 50 second delays for the system clock to wrap around. To see how this happens, simulate your program on a piece of paper with the OnTime and OffTime values.
  • tmaynardtmaynard Posts: 27
    edited 2010-06-08 20:44
    Thank you, Gentlemen, but none of the proposed solutions work!

    TonyP12 and Kye's suggestions really amount to the same thing, and I get one quick flash (1/4 sec), and then a steady stream of 3/4 sec flashes.

    Mike's idea produces a series of 1/4 second flashes only. Not exactly what I'm looking for.

    I want the LED to be ON for 1/4 second, and OFF for 3/4 second. Like so, from the PE Kit book:
    PUB LedOnOff
    
        dira := 1
        
        repeat
            outa := 1
            waitcnt(clkfreq/4 + cnt)
            outa := 0
            waitcnt(clkfreq/4*3 + cnt)
    
    


    Tom.
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2010-06-08 21:11
    Haven't tested this but this should work.

    -Jack

    org     0
    entry                       
                            or      dira, Pin               ' Select P4 for output (1)
                            andn    outa, Pin               ' Set P4 low (0)
    
                            mov     counter, OffDelay        ' Set up delays on/off
                            add     counter, cnt
    
    
    :loop
                            waitcnt counter, OnDelay    ' Pause 3/4 sec
                            or     outa, Pin                   ' Turn on LED
                            waitcnt counter, OffDelay   ' Pause 1/4 sec
                            andn     outa, Pin               ' Turn off LED
                            jmp     #:loop
    
    
    
    
    Pin                     long    |< 4
    
    OnDelay                 long    80_000_000 / 4
    OffDelay                long    (80_000_000 / 4) * 3
    
    
    Counter                 res     1
    
                            fit
    
  • tmaynardtmaynard Posts: 27
    edited 2010-06-08 21:18
    Jack Buffington said...
    Haven't tested this but this should work.
    Indeed it does! I'm going to have to pound this into my head (which is 90% bone).

    Thanks to one and all for your suggestions.
Sign In or Register to comment.