Shop OBEX P1 Docs P2 Docs Learn Events
My first PASM — Parallax Forums

My first PASM

Bobb FwedBobb Fwed Posts: 1,119
edited 2009-02-02 22:07 in Propeller 1
I am working on my first PASM program (first "machine language" program ever).
I am converting a rather trivial program over to PASM. It is a LED control program I use to not slow down the controller cog. I have the SPIN version, and my attempt at the the PASM. The PASM seems to work somewhat, but it starts a couple seconds later than it seems it should, the type 4 blink doesn't work at all, and it only seems to loop once. Please take a look and help me out.
SPIN:
VAR
  byte cog, cogon
  long ledstack[noparse][[/noparse]20]        
  long ledblink

PUB Main
  LED(0, 1)

PUB LED (pin1, pin2)
  stop
  cogon := (cog := cognew(dance(pin1, pin2, @ledblink), @ledstack)) > 0
  REPEAT
    waitcnt(clkfreq + cnt)
    blinktype(1)
    waitcnt(clkfreq + cnt)
    blinktype(2)
    waitcnt(clkfreq + cnt)
    blinktype(4)
    waitcnt(clkfreq + cnt)
    blinktype(3)

PUB stop
  if cogon~      
    cogstop(cog)

PUB blinktype (type)
  ledblink.byte[noparse][[/noparse] 3 ] := type                                            ' shove to high byte
  
PUB dance (pin1, pin2, typeAddr) | lled, i
  OUTA[noparse][[/noparse]pin1]~
  OUTA[noparse][[/noparse]pin2]~
  DIRA[noparse][[/noparse]pin1]~~
  DIRA[noparse][[/noparse]pin2]~~

  REPEAT                                                              ' repeat forever
    REPEAT UNTIL (lled := byte[noparse][[/noparse]typeAddr])                             ' repeat nothing until type is set
      long[noparse][[/noparse]typeAddr] >>= 8

    long[noparse][[/noparse]typeAddr] >>= 8

    CASE lled
      1:                                                              ' green 
        OUTA[noparse][[/noparse]pin1]~
        OUTA[noparse][[/noparse]pin2]~~

      2:                                                              ' yellow 
        OUTA[noparse][[/noparse]pin1]~~
        OUTA[noparse][[/noparse]pin2]~

      3:                                                              ' off 
        OUTA[noparse][[/noparse]pin1]~
        OUTA[noparse][[/noparse]pin2]~     

      4:                                                              ' blink: to show "on" -- switches color
        REPEAT 2
          pause(250)                                                              
          !OUTA[noparse][[/noparse]pin1]
          !OUTA[noparse][[/noparse]pin2]

PUB pause (pause_ms) 
  waitcnt(((clkfreq / 1000 *  pause_ms) #> 381) + cnt)



PASM:
CON

  LED1_p = 0
  LED2_p = 1

OBJ

VAR
  byte cog, cogon
  word high_wait, low_wait
  long ledblink

PUB LED | i
  stop
  cogon := (cog := cognew(@dance, @ledblink)) > 0
  REPEAT
    waitcnt(clkfreq + cnt)
    blinktype(1)
    waitcnt(clkfreq + cnt)
    blinktype(2)
    waitcnt(clkfreq + cnt)
    blinktype(4)
    waitcnt(clkfreq + cnt)
    blinktype(3)

PUB stop
  if cogon~      
    cogstop(cog)

PUB blinktype (type)
  ledblink.byte[noparse][[/noparse] 3 ] := type                                            ' shove to high byte

DAT

                        ORG 0

dance
                        MOV       DIRA, LED_p
                        MOV       OUTA, #0

danceloop                                             ' loop forever
        :loop
                        RDBYTE    ledtype, PAR  WZ
                        RDLONG    shft, PAR
                        SHR       shft, #8
                        WRLONG    shft, PAR 

              IF_NZ     JMP       #caseswitch
                        JMP       #:loop

caseswitch                                            ' same as switch/case
        type1                                         ' LED green
                        CMP       ledtype, #1   WZ 
              IF_NZ     JMP       #type2
                        MOV       OUTA, GREEN
                        JMP       #danceloop

        type2                                         ' LED yellow
                        CMP       ledtype, #2   WZ
              IF_NZ     JMP       #type3
                        MOV       OUTA, YELLOW
                        JMP       #danceloop      

        type3                                         ' LED off
                        CMP       ledtype, #3   WZ
              IF_NZ     JMP       #type4
                        MOV       OUTA, #0
                        JMP       #danceloop          

        type4                                         ' blink color back and forth
                        CMP       ledtype, #4   WZ
              IF_NZ     JMP       #type5
                        MOV       idx, #2
        :loop
                        MOV       OUTA, NOT OUTA
                        MOV       waitlen, cnt
                        ADD       waitlen, pausetime
                        WAITCNT   waitlen, pausetime
                        DJNZ      idx, #:loop
                        JMP       #danceloop                   

        type5        
                        JMP       #danceloop          ' back to top

LED_p                   LONG      |< LED1_p | |< LED2_p
YELLOW                  LONG      |< LED1_p
GREEN                   LONG      |< LED2_p
pausetime               LONG      1_000_000
waitlen                 LONG      0
shft                    LONG      0
idx                     LONG      0
ledtype                 BYTE      0

                        FIT 496



Edit: fixed mCode formatting issue

Post Edited (Bobb Fwed) : 2/2/2009 9:45:43 PM GMT

Comments

  • mparkmpark Posts: 1,305
    edited 2009-02-02 21:02
    What is the purpose of the shifts here?·
        REPEAT UNTIL (lled := byte[noparse][[/noparse]typeAddr])                             ' repeat nothing until type is set
          long[noparse][[/noparse]typeAddr] >>= 8
    
        long[noparse][[/noparse]typeAddr] >>= 8
    
    

    You're doing something similar in the PASM code and to me it just looks like trouble. You're watching a memory location to see if it becomes non-zero, but at the same time you're continually writing a zero into it. There's a very small window of time for the other cog to set the blink type. The window is even smaller for the PASM version.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-02-02 21:19
    So here's the idea: Controller cog starts LED cog, then periodically sends it a blink type to output the user. The setup is a queue, so if the controller cog sends another blink before the first is done, it gets put in the queue. The shifting moves the items waiting in the queue up one notch.
    When the controller cog calls blinktype(), it sets byte 3 to the value.
    While the LED cog is waiting, it shifts that value toward byte 0. Once it is reached, it executes that value.

    I realize that I should be locking those addresses during the operation, but I haven't had a problem yet with the SPIN version. The blink type commands can be sent as close as 1000 cycles from each other, and some of the blinktypes (not all are listed in the program) are as long as 60 seconds. So if the 60 second command gets called, at least one more command is queued while that is happening. In the final version, I'd like 4 more queued, but I'll have to get this working before I get to that.

    REPEAT UNTIL (lled := byte[noparse][[/noparse]typeAddr])                             ' repeat nothing until type is set
          long[noparse][[/noparse]typeAddr] >>= 8  ' shift bytes right toward byte 0, so at some point the above code will not fail
    
  • mparkmpark Posts: 1,305
    edited 2009-02-02 21:40
    Is there a "[noparse][[/noparse]3]" in your code that isn't showing up here?
    PUB blinktype (type)
      ledblink.byte := type                                            ' shove to high byte
    
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-02-02 21:44
    Ah, yes, that is now fixed....dang mCode!
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-02-02 21:54
    I now realize (after testing the posted code) that it doesn't work as well as it did when I had some waitcnt()s inside the REPEAT UNTIL (lled := byte[noparse][[/noparse]typeAddr]) loop. That pause probably gave it enough time to receive commands.
    OK. New task, can someone explain explain how the lock tasks work? I assume I locknew and get an ID, but how do I tell it what information is locked? Then I use lockset. When I am not accessing the info I use LockClr?
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-02-02 22:07
    So does
    MOV       OUTA, NOT OUTA
    

    work? What is the best way to toggle a set of pins (like !OUTA[noparse]/noparse does in SPIN)
Sign In or Register to comment.