Shop OBEX P1 Docs P2 Docs Learn Events
Propeller doing odd things when programming with PASM — Parallax Forums

Propeller doing odd things when programming with PASM

hayden12w3hayden12w3 Posts: 4
edited 2017-06-13 04:18 in Propeller 1
Hello all!

I've been taking a swing at assembly coding in the Propeller for a project I've been working on. I have gotten a few individual codes to work well, my favorite being code that controls a '595 shift register. Once I start increasing the complexity of any code (more CMP, if_z, stuff like that) everything goes south. Currently I'm working on code that reads two pins and shifts out a number based on which pins are high and how many times a certain pin has pulsed. The code works well if I just compare the inputs to one number, but once I write in the code to do something based on other stages of the input, random parts of the code stop working. This code is mainly testing certain aspects of assembly coding so that I can make my main project work. What I need to know is what exactly is causing the code to act funny. I'll attach my code and also some pictures of the oscilloscope screen describing what is happening. Also, I'm new to this forum so let me know if there's a way to streamline my posts better with image and code attachments. Thanks!
2688 x 1520 - 1M
2688 x 1520 - 1M

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-13 04:53
    Hi Hayden, welcome to the forum. The org directive means something as you have not put your variables for each cog after the code for that cog. So have a look at the listing and you will see that you a writing to variables at locations where code exists. (i.e. inputs)

    btw, just a little point but if "zero" is always meant to be zero then why not say "#0" rather than allocating a register for it?
    |===========================================================================|
    Objects : -
    Untitled2
    
    Object Address : 0010 : Object Name : Untitled2
    
    Binary Image Information :
    PBASE : 0010
    VBASE : 0118
    DBASE : 0120
    PCURR : 010C
    DCURR : 0124
    |===========================================================================|
    |===========================================================================|
    Object Untitled2
    Object Base is 0010
    |===========================================================================|
    Object Constants
    |===========================================================================|
    Constant _clkmode = 00000408 (1032)
    Constant _xinfreq = 004C4B40 (5000000)
    |===========================================================================|
    Object DAT Blocks
    |===========================================================================|
    0018(0000)             |         org 0
    0018(0000) 07 EC FF A0 | Output  mov             dira, #$7
    001C(0001) FF 3A FC A0 |         mov             inputs, #$FF
    0020(0002) F2 3B BC 60 |         and             inputs, ina
    0024(0003) 03 3A FC 38 |         sar             inputs, #3
    0028(0004) 1B 34 3C 86 |         cmp             zClear, zero wz
    002C(0005) 03 3A 7C 86 |         cmp             inputs, #$3 wz
    0030(0006) 01 38 E8 A0 |         if_z            mov  injector, #$1
    0034(0007) 0D 00 68 5C |         if_z            jmp  #Shift
    0038(0008) 1B 34 3C 86 |         cmp             zClear, zero wz             'Adding these commented out lines of code causes the program to act weird
    003C(0009) 01 3A 7C 86 |         cmp             inputs, #$1 wz              '
    0040(000A) 01 38 E8 2C |         if_z            shl  injector, #1           '
    0044(000B) 0D 00 68 5C |         if_z            jmp  #Shift                 '
    0048(000C) 00 00 7C 5C |         jmp             #Output
    004C(000D) 1C 42 BC A0 | Shift   mov             save, injector     'injector input value
    0050(000E) 00 40 FC A0 |         mov             iterA, #0
    0054(000F) 01 44 FC A0 | Loop    mov             mask, #$1
    0058(0010) 21 44 BC 60 |         and             mask, save
    005C(0011) 22 E8 BF 6C |         xor             outa, mask
    0060(0012) 02 E8 FF 6C |         xor             outa, #$2
    0064(0013) 00 00 00 00 |         nop
    0068(0014) 02 E8 FF 6C |         xor             outa, #$2
    006C(0015) 00 E8 FF 60 |         and             outa, #$0
    0070(0016) 01 42 FC 38 |         sar             save, #1
    0074(0017) 01 40 FC 80 |         add             iterA, #1
    0078(0018) 1B 34 3C 86 |         cmp             zClear, zero wz
    007C(0019) 08 40 7C 86 |         cmp             iterA, #8  wz
    0080(001A) 1C 00 68 5C |         if_z            jmp #Latch
    0084(001B) 0F 00 7C 5C |         jmp             #Loop
    0088(001C) 04 E8 FF 6C | Latch   xor             outa, #$4
    008C(001D) 00 00 00 00 |         nop
    0090(001E) 04 E8 FF 6C |         xor             outa, #$4
    0094(001F) 00 00 7C 5C |         jmp             #Output
    0098(0020)             |         org 0
    0098(0000) 17 EC BF A0 | Cycle   mov             dira, Pin
    009C(0001) 00 3C FC A0 |         mov             iter, #0
    00A0(0002) 17 E8 BF 6C | Start   xor             outa, Pin
    00A4(0003) F1 3F BC A0 |         mov             Time, cnt
    00A8(0004) 18 3E BC 80 |         add             Time, Pulse
    00AC(0005) 18 3E BC F8 |         waitcnt         Time, Pulse
    00B0(0006) 17 E8 BF 6C |         xor             outa, Pin
    00B4(0007) F1 3F BC A0 |         mov             Time, cnt
    00B8(0008) 19 3E BC 80 |         add             Time, Delay
    00BC(0009) 19 3E BC F8 |         waitcnt         Time, Delay
    00C0(000A) 01 3C FC 80 |         add             iter, #1
    00C4(000B) 08 E8 FF 6C | LoopA   xor             outa, #$8
    00C8(000C) F1 3F BC A0 |         mov             Time, cnt
    00CC(000D) 18 3E BC 80 |         add             Time, Pulse
    00D0(000E) 18 3E BC F8 |         waitcnt         Time, Pulse
    00D4(000F) 08 E8 FF 6C |         xor             outa, #$8
    00D8(0010) F1 3F BC A0 |         mov             Time, cnt
    00DC(0011) 19 3E BC 80 |         add             Time, Delay
    00E0(0012) 19 3E BC F8 |         waitcnt         Time, Delay
    00E4(0013) 01 3C FC 80 |         add             iter, #1
    00E8(0014) 08 3C 7C 86 |         cmp             iter, #8  wz
    00EC(0015) 00 00 68 5C |         if_z            jmp   #Cycle
    00F0(0016) 0B 00 7C 5C |         jmp             #LoopA
    00F4(0017) 18 00 00 00 | Pin           long  $18
    00F8(0018) 2C 01 00 00 | Pulse         long  300       'Pulsewidth ~ Pulse*12.5
    00FC(0019) 20 BF 02 00 | Delay         long  180_000   'Delay between pulses ~ Delay*12.5
    0100(001A) FF FF FF FF | zClear        long  $FFFF_FFFF
    0104(001B) 00 00 00 00 | zero          long  $0000_0000
    0108(001C) 00 00 00 00 | injector      long  0
    010C(001D)             | inputs        res 1
    010C(001E)             | iter          res 1
    010C(001F)             | Time          res 1
    010C(0020)             | iterA         res 1
    010C(0021)             | save          res 1
    010C(0022)             | mask          res 1
    |===========================================================================|
    |===========================================================================|
    Spin Block Main with 0 Parameters and 0 Extra Stack Longs. Method 1
    PUB Main
    
    Local Parameter DBASE:0000 - Result
    |===========================================================================|
    6                              cognew(@Output, 0)
    Addr : 010C:             34  : Constant 0 $FFFFFFFF
    Addr : 010D:          C7 08  : Memory Op Long PBASE + ADDRESS Address = 0008
    Addr : 010F:             35  : Constant 1 $00000000
    Addr : 0110:             2C  : CogInit(Id, Addr, Ptr)
    7                              cognew(@Cycle, 0)
    Addr : 0111:             34  : Constant 0 $FFFFFFFF
    Addr : 0112:       C7 80 88  : Memory Op Long PBASE + ADDRESS Address = 0088
    Addr : 0115:             35  : Constant 1 $00000000
    Addr : 0116:             2C  : CogInit(Id, Addr, Ptr)
    Addr : 0117:             32  : Return
    
  • Mr. Jakacki, Thank you for your quick response! Moving those variables to their proper spots fixed the problem immediately! I was under the impression for a while that all of the variables regardless of which cog they belonged to went at the bottom of the code, I now see that was incorrect! Not really sure why I had a variable set up as zero, I tend to stay up late when I program so I'm guessing it has something to do with that. I still have a long way to go on this project so I will keep y'all updated if (when) I run into any issues.
    Thanks again! Have a good one!
  • I thought staying up late was the whole point of programming, seeing that debugging is the art of removing bugs from a program, then programming must be the art of putting them in there in the first place! :)
  • I thought staying up late was the whole point of programming, seeing that debugging is the art of removing bugs from a program, then programming must be the art of putting them in there in the first place! :)
    Lol

  • To enter code, simply use [ code ] your code here [ /code ] tags, or click the C on the toolbar.

    A couple things, besides declaring a zero variable, what's the intention of
            cmp             zClear, zero wz
            cmp             inputs, #$3 wz
    
    Both instructions affect the Z flag, the 1st will always clear the flag, and the 2nd will overwrite the 1st regardless.

    For your time delays:
            mov             Time, cnt
            add             Time, Pulse
            waitcnt         Time, Pulse
            xor             outa, #$8
            mov             Time, cnt
            add             Time, Delay
            waitcnt         Time, Delay
            add             iter, #1
    
    is perfectly fine for fixed delays, however you can produce synchronized delays with:
            mov             Time, Pulse
            add             Time, cnt                  ' Establish 1st delay
            waitcnt          Time, Pulse            ' Wait, automatically increments Time with Pulse
            xor              outa, #$8
            waitcnt          Time, Pulse            ' Wait pulse duration from previous waitcnt
    
    The Prop manual has a decent writeup under the waitcnt section, page 220.

    Welcome to the forum.

    Chris
  • Chris, I think the Z-flag magic I had there was me previously trying to work around a problem I had with some CMP executions. I now realize (thanks to Mr. Jakacki) that those problems probably stemmed from my incorrect usage of the variable initialization part of the code rather than any Z-flag issues. I'll remove those lines from the code once I get off work. As far as the time delays go, what exactly do you mean by synchronized delays? Thanks for your responses by the way.
  • JonnyMacJonnyMac Posts: 8,927
    edited 2017-06-13 18:21
    As we say in Hollywood... for your consideration:
    loop_a          mov     iter, #8
                    mov     time, pulse
                    add     time, cnt
                     
    :loop           or      outa, #$08
                    waitcnt time, delay
                    andn    outa, #$08  
                    waitcnt time, pulse
                    djnz    iter, #:loop
                    jmp     #cycle
    
    In a synchronized loop the cnt register is accessed just before entering the loop -- everything is a delta from that, and waitcnt simplifes what you want to do. Since you seem to want distinct high and low timing values for pin 8, I would suggest dropping xor for andn (low) and or (high). The djnz instruction is optimized for looping, so that's another way to simplify the loop code.

    I may be missing some bits as I'm kind of doing a drive-by to clear my head of a Propeller schematic I'm working on. Hopefully, though, some of this is helpful.
  • A synchronized delay is useful for timing intervals, such as in a serial UART. At say 9600bps each bit is ideally 1.04us long, which is easily maintained with a synchronized delay but could drift with a fixed delay due to instruction overhead.

    In Spin, this fragment sends one bit every 104us plus the amount of time it takes to twiddle the IO pin:
      repeat 10
         waitcnt(104us + cnt)
         sendBit
    
    whereas a synchronized delay might look like:
       delayTime := 104us + cnt
       repeat 10
          waitcnt(delayTime)     
          delayTime := delayTime + 104us
          sendBit
    
    This sends a bit every 104us regardless of the amount of overhead...provided that it returns to the waitcnt prior to the next interval, otherwise it'll wait for the cnt to roll around again.
    If you ever encounter a problem where the code seems to hang for ~53 seconds, this's likely to be the problem.

    In PASM, the waitcnt instruction waits the delay specified by the 1st operand, and then automatically adds the 2nd operand to the 1st.
         waitcnt   delay,next
    
    is similar to
         waitcnt   delay,0
         add       delay,next
    
    Both types of delay have their uses, right tool for the right job and all.
  • Just wanted to say thanks again for all of the help y'all! I got the code working and my project is now going swimmingly thanks to all of the help. I'll try to post updates on the project as it goes along.
    Y'all are the best!
Sign In or Register to comment.