Shop OBEX P1 Docs P2 Docs Learn Events
Need some PASM help with passing values from Spin — Parallax Forums

Need some PASM help with passing values from Spin

PainlessPainless Posts: 69
edited 2009-09-16 16:11 in Propeller 1
I've haven't been able to play with my prop for quite some time, which is annoying as I was just starting to dig into PASM when I had to divert my free time elsewhere (*sigh* isn't that always the way?). I'm now working on a controllable PWM for another project (earth safe or green energy is my other hobby) but am having issues with getting data to the assembler from spin.

Here's the idea: The spin program (once I get the data passing right) will control a serial terminal through which the user can alter the PWM parameters (duty cycle, frequency etc), whenever the parameters change the spin program will stop the PWM PASM cog, supply the new parameters and start it again. The PWM PASM cog will start up, read its parameters into cog ram and then start a nice tight PWM loop. I figure with the instructions I have at the moment I should be able to get up to almost 4khz from the PWM. Naturally, I want to keep the PWM parameters in cog ram for speed.

My problem is I just cannot seem to get the parameter passing correct (just the on/off time at the moment) and it seems to be overwriting the other cog data such as the pin variable (I'm testing on a LED block atm). I'm sure that I'm just not understanding something very basic, I haven't programmed in assembler since I was 12 years old (I'm 39 now) and that was Z80.

Anyhow, here's my skeleton testing code at the moment, any help would be gratefully received:

CON

  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

VAR

  byte cog
  long delaytime

PUB Main

  StartPWM(10000000)

PRI StartPWM (timep)

  delaytime := timep
  cog := cognew(@pwm, @delaytime)

PRI StopPWM

  cogstop (cog)

DAT

              org     0

pwm       mov     dira, pin         'Set pin to output for the PWM signal
              rdlong  delay, par      'Get the delay time in clocks
              mov     time, cnt        'Record the current clk
              add     time, delay      'Add the required delay
       
loop        xor     outa, pin         'Turn on pin
              waitcnt time, delay     'Wait until the end of the required delay
              xor     outa, pin         'Turn off pin
              waitcnt time, delay     'Wait until the end of the required delay
              jmp     #loop          'Lets go round again!

time        res     1
delay       long   0
pin           long   |>16   




Thanks again for any input.

Russ.

Comments

  • BradCBradC Posts: 2,601
    edited 2009-09-16 12:51
    Painless said...

    time        res     1
    delay       long   0
    pin           long   |>16   
    
    



    Repeat after me. "res goes after everything else". Now write it out 100 times!

    It's a common beginners mistake. It bit me more than once when I was coming to grips with PASM.

    Put your "time" variable after everything else and it should work nicely.

    Here is the assembly listing of your code.
    If you look at the bottom you will see that the way the hub loads the cog will put the contents of your "delay" where you think "time" should be... no biggie in your code,
    but then it puts "pin" where "delay" should be. "pin" ends up being filled with the header of the SPIN object (which is not what you want at all and will cause odd behaviour)

    |===========================================================================|
    Object DAT Blocks
    |===========================================================================|
    001C(0000)             |               org     0
    001C(0000) 0B EC BF A0 | pwm       mov     dira, pin         'Set pin to output for the PWM signal
    0020(0001) F0 15 BC 08 |               rdlong  delay, par      'Get the delay time in clocks
    0024(0002) F1 13 BC A0 |               mov     time, cnt        'Record the current clk
    0028(0003) 0A 12 BC 80 |               add     time, delay      'Add the required delay
    002C(0004) 0B E8 BF 6C | loop        xor     outa, pin         'Turn on pin
    0030(0005) 0A 12 BC F8 |               waitcnt time, delay     'Wait until the end of the required delay
    0034(0006) 0B E8 BF 6C |               xor     outa, pin         'Turn off pin
    0038(0007) 0A 12 BC F8 |               waitcnt time, delay     'Wait until the end of the required delay
    003C(0008) 04 00 7C 5C |               jmp     #loop          'Lets go round again!
    0040(0009)             | time        res     1
    0040(000A) 00 00 00 00 | delay       long   0
    0044(000B) 10 00 00 00 | pin           long   |>16
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lt's not particularly silly, is it?
  • PainlessPainless Posts: 69
    edited 2009-09-16 13:57
    Brad,

    Thank you! I knew it would be something silly. I also spotted another bug in my pin statement, I used |> instead of |<.

    One more question, if I may, what is the difference between:

    time       res     1
    
    



    and

    time       long    0
    
    



    both use one long of storage, but other than that what is the difference? Both are in cog ram I believe? Is it simply the versatility with res of reserving X number of longs in one go?

    Russ.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-09-16 14:08
    When a cog is started up with a COGNEW or COGINIT, 512 longs are copied from the hub memory to the cog's memory regardless of how much code you put in the DAT section you're using. Whatever is sitting in the hub memory "above" the PASM program is copied if you wrote less than 512 longs. Often that's compiled Spin code from some other part of your program and it doesn't really matter.

    If you use "time long 0", a long of zero is compiled into your program and eventually copied into the cog memory.

    If you use "time res 1", nothing is compiled into your program, but the compiler assigns the next cog memory location to the label "time". This works fine if the "res" statements are at the end of the cog's program, but doesn't work if you follow the "res" statements with something else (an instruction or "long" statement) and expect it to be in the proper place in hub memory so it can be copied to where you expect it in the cog's memory.

    The main reason for having "res" is that hub memory is limited (32K bytes) and 512 longs are always copied to the cog. If you want to allocate variables in a cog program, but don't care about the initial value, you don't need to set aside hub memory as a placeholder. You can let the Spin compiler use the space for something else.

    Post Edited (Mike Green) : 9/16/2009 2:15:28 PM GMT
  • PainlessPainless Posts: 69
    edited 2009-09-16 14:28
    Thank you for your reply, Mike.

    What you're saying makes good sense. Would I be correct to assume then that if I created longs in my PASM DAT section and assigned them values via the initial spin code, when the PASM cog is started those values will be available in cog ram to the PASM program?

    For example:

    CON
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
    VAR
    
      byte cog
    
    PUB Main
    
      StartPWM(5000, 1000)
    
    PRI StartPWM (ont, offt)
    
      ontime := ont
      offtime := offt
      cog := cognew(@pwm, 0)
    
    PRI StopPWM
    
      cogstop (cog)
    
    DAT
    
                  org     0
    
    pwm       mov     dira, pin         'Set pin to output for the PWM signal
                  mov     time, cnt         'Record the current clk
                  add     time, ontime       'Add the required delay
           
    loop        xor     outa, pin              'Turn on pin
                  waitcnt time, offtime       'Wait until the end of the required delay
                  xor     outa, pin              'Turn off pin
                  waitcnt time, ontime        'Wait until the end of the required delay
                  jmp     #loop           'Lets go round again!
    
    pin          long  |<15
    ontime    long 0
    offtime    long 0
    
    



    .... would this serve my purpose for passing my values to the assembler without it having to access hub ram?

    Russ.

    Post Edited (Painless) : 9/16/2009 2:33:55 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2009-09-16 14:51
    Yes. If you assign values to long variables in a DAT section, those values will be copied to the cog when you start it up with COGNEW / COGINIT.
  • PainlessPainless Posts: 69
    edited 2009-09-16 16:11
    Thank you, Mike.
Sign In or Register to comment.