Shop OBEX P1 Docs P2 Docs Learn Events
Will there ever be a detailed guide to getting started in PASM? — Parallax Forums

Will there ever be a detailed guide to getting started in PASM?

photomankcphotomankc Posts: 943
edited 2009-12-14 20:10 in Propeller 1
I keep running into a wall getting started in PASM beyond maybe blinking a light.· It is just not working for me to try and dig through scattered bits of code here and there.· I just feel like I am groping in the dark much of the time.· Will there ever be a solid book or tutorial along the lines of the PELabs kit material for PASM?· I have looked through the tutorials from DeSilva and a couple others but I feel like I'm spinning my wheels trying to get a solid grasp of putting all this stuff together.· I'm working on a project now where the speed of PASM is simply required.

I'm dying to get my hands on PropBasic just for the simple fact that I can write something out in a HLL and see it translated to PASM for some help with the basics of value passing and various logic constructs.

Comments

  • StefanL38StefanL38 Posts: 2,292
    edited 2009-12-13 11:59
    As you have a concrete project that you would like to work on

    Did you ever try to work with PASD ?
    The site is german but the manual is in english.

    And second option:
    Just post your PASM-code here.
    Most questions are on SPIN in the forum. But there are several PASM-gurus online here too.
    Just post one of your codes with a concrete description what you would like to do.
    I'm sure: as long as you ask CONCRETE questions you can ask as many and as simple questions you like
    and you will get answers.

    To learn PASM I used the technique to modify a working example command by command
    or by jump to a subroutine that makes an LED blink if something works as I expected it and does not blink if it works different.

    Once I started a thread What methods do you use to debug PASM-code ?

    Read the comments to see if you find something useful of the suggestions there

    best regards

    Stefan
  • Chris_DChris_D Posts: 305
    edited 2009-12-13 13:39
    With a bit of luck, I hope to have some time next year to put together some sort of beginners guide to PASM.· I am by no means a PASM expert, but I have been working with it enough in the past few months to be able to help beginners to get going with it.· Unfortunately right now my plate is very full so the earliest I can do something would be about 3 to 4 months away.

    Chris
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-13 14:16
    This may be one of the things you have already seen but I created a set of example programs designed to get people started in assembly:

    Assembly step by step

    It does not cover everything but it does show you the key steps that can get you writing useful programs, things like masking and getting data from cog to hub and visa versa. I wrote it because once I had learnt these things (the hard way) I wanted to share.

    I've been thinking about trying to create a proper tutorial that covers much more, my feeling is that a video, probably animated could be an excellent way to explain the principles, the animation would probably include screen capture and real animation (a great way to show how bitwise masking and carry flags work etc). However I am not an expert myself and it would probably be a massive undertaking, I will probably try something on a small scale first and see how it pans out.

    Graham
  • ericballericball Posts: 774
    edited 2009-12-13 16:11
    To a large extent PASM can be learned from the Propeller Manual if, and here's the rub, you are already an experienced assembly language programmer.· The biggest challenge is groking the COG RAM register == instruction == long equivalence.

    But if your only programming experience is with high level languages like C, Java, Basic and SPIN then PASM is going to be very difficult to learn.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Composite NTSC sprite driver: Forum
    NTSC & PAL driver templates: ObEx Forum
    OnePinTVText driver: ObEx Forum
  • SRLMSRLM Posts: 5,045
    edited 2009-12-13 16:28
    It might help if you learn about computer architecture first, then learn PASM. For me I learned how the computer works at the gate and RTL, then learning an assembly language was very clear because the design of the language mimics the design of the hardware. Of course, learning about computer architecture will take a while and a lot of reading if you don't have a good teacher.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Powered by enthusiasm
  • photomankcphotomankc Posts: 943
    edited 2009-12-13 20:17
    Ok, here's my concrete example. smile.gif

    I'm working on a potential CNC controller. The basic idea is that it can be switched between total computer control or some form of stand alone mode where it would work more like a power drive w/DRO. In the PC controlled mode it must be able to respond to very fast positive pulses on the clock line. Reading seems to indicate CNC software is putting out pulses of 1 to 15us. My spin code can, at it's limit catch an 18us positive pulse and get that copied to the output lines. It then does it's back-end position tracking and then generates the falling edge. Of course my output pulse is much fatter (46us) than the input but I don't think the chip cares. This gives me ability to respond to pulses at around 12KHz max. The direction signal has to hit the line at least 2us before the clock so I have to stop and copy just it across first. My main concern is that I can't capture those really small clock pulses the CNC software will put out. They seem to send pulses of around 1-3us by default and I'm not sure how configurable the various packages are for that.

    With PASM I would have plenty of time to track position and possibly some other processing as well like changing settings or tracking input vs. output steps to detect being driven to fast. The basic ideas of mov, add, cmp, jmp and such I have a rough understanding of even a bit of the self-modifying concepts. It's setting up the initial configuration to the user configured pins and getting the variables back and forth that I get lost in.

    This is my way incomplete code but I want the input driven code to work first. I think Spin will work just fine for stand alone mode. My idea is that to change modes the cog is stopped and a new cog is launched to run the selected mode.

    I'll attach where I am so far.· Where I have been going nowhere is is in reading the next ram values by offsets from PAR like invertDir or position.· I did at least get the correct lights on my step mode outputs so that was exciting!

    Post Edited (photomankc) : 12/13/2009 8:23:23 PM GMT
  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-12-13 20:21
    You might have a look at my "Spin Zone" articles. I made the decision when switching from the Stamp to the Propeller with my column that I would always include some PASM in every project. As a "regular guy" programmer who has to explain things, none of what I do is terribly difficult, though most find it useful. Perhaps you will, too.

    www.parallax.com/Resources/NutsVoltsColumns/TheSpinZone/tabid/781/Default.aspx
  • photomankcphotomankc Posts: 943
    edited 2009-12-13 22:48
    Well I've made it a little further....,

    I now get the correct initial outputs, and I can capture the first rising edge.· After that it never goes back to low even if the pins match the states in the condition.· I'm stumped.· It also doesn't react to changes on the ENA_IN line as I expect it to.
  • mikedivmikediv Posts: 825
    edited 2009-12-13 23:37
    Graham Stabler I had never seen your post before very nice thank you
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-14 00:12
    Thanks Mike!

    photomankc,

    It looks like you are doing a great job of learning assembly to be honest, you have got much further than many! I think your problem is with the use of OR.

    We can use OR to set bits high of course so if we know all bits are currently low then we can use it to set some bits to a particular pattern e.g.

     mov   a,#0    ' clear register a
     or      a,b      ' puts bit pattern of b on a
    
    



    However what if the register a is not cleared but you still want it to reflect the pattern in b. Any bit in a that is high will still be high after being ORed with b even if the corresponding bit in b is zero.

    so when you do:

       or        outa,       t1                  'Put the current signals on the wire
    
    



    You are not actually putting the current signals on the wire in fact most probably they will all just end up as 1 as the OR can never make them zero.

    I think what you need to do is use the muxnz command (p317). This will set the bits in the destination register equal to !Z for the bits that are high in the source register. So in your case you would do:

        muxnz outa, t1
    
    



    This assumes the z flag is not set. If it might be set any mov command with a non zero value will clear it.

    I hope that helps

    Graham
  • photomankcphotomankc Posts: 943
    edited 2009-12-14 00:25
    Definitely a big help Graham.....

    I was just thinking the same thing about the or-ing.·

    I'm still not seeing a way to handle this:
    out[noparse][[/noparse]3..5] := ina[noparse][[/noparse]0..2]
    

    I have no forward knowledge of what each pin might be set to at any moment, I'm just wanting to mirror what they are across the chip.· I have to react to either enable or step changing states and get that over to the outputs and of course they are opposites.

    Post Edited (photomankc) : 12/14/2009 12:47:47 AM GMT
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-14 00:36
    Oh heck of course. What I have suggested will not work either. I'll have a think

    Graham
  • photomankcphotomankc Posts: 943
    edited 2009-12-14 00:51
    Where are you doing that in here?

    :loop         waitpne   startState, waitMask
                  mov       t1,         ina                 'Get the current inputs
                  and       t1,         insMask             'Mask out everything but control inputs
                  shr       t1,         #STP_IN             'Shift bits to low byte
                  shl       t1,         #CLK_OUT            'Shift bits to postion of outputs
    

    Sorry if I'm dense here.· This is why I always walked away from assembly.· Everything is so tedious.
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-14 00:53
    (sorry I deleted this first time after a crisis of confidence)

    I think I have it:

       mov  temp,outa     ' make a copy of outa
       xor   temp, t1        ' or with t1, bits that need changing in outa will be 1 in temp
       or    temp, mask    ' mask so we don't consider all the bits in outa
       xor  outa,temp      ' Now toggle the bits that need toggling
    
    



    I am sure this is standard practise for proper programmers but I had to reinvent it [noparse]:)[/noparse]

    A:outa  |   B:T1 |  C:XOR of A and B | D:XOR of A and C = B
       0    |    0   |        0          |           0
       0    |    1   |        1          |           1
       1    |    0   |        1          |           0 
       1    |    1   |        0          |           1  
    
    



    Graham

    Post Edited (Graham Stabler) : 12/14/2009 1:06:35 AM GMT
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-14 01:00
    So in your code something like:
                  waitpeq   startState, waitMask
                  mov       t1,         ina                 'Get the current inputs
                  and       t1,         insMask             'Mask out everything but control inputs
                  shr       t1,         #STP_IN             'Shift bits to low byte
                  shl       t1,         #CLK_OUT            'Shift bits to postion of outputs
                  mov       t2,         outa                'Get current state of outa
                  and       t2,         outsmask            'Mask for output pins only
                  xor       t2,         t1                  'Xor (high bits in t2 are bits that need toggling in outa)
                  xor       outa,       t2                  'Toggle pins as required
    
    

    Post Edited (Graham Stabler) : 12/14/2009 10:13:07 AM GMT
  • photomankcphotomankc Posts: 943
    edited 2009-12-14 01:27
    Nope.
    Although it's fast as hell while it plows everything under.
    noninv        mov       t1,         ina                 'Get the current inputs
                  and       t1,         insMask             'Mask out everything but control inputs
                  shr       t1,         #STP_IN             'Shift bits to low byte
                  shl       t1,         #CLK_OUT            'Shift bits to postion of outputs
                  or        outa,       t1                  'Put the current signals on the wire
    

    :loop         waitpne   startState, waitMask
                  mov       t1,         ina                 'Get the current inputs
                  and       t1,         insMask             'Mask out everything but control inputs
                  shr       t1,         #STP_IN             'Shift bits to low byte
                  shl       t1,         #CLK_OUT            'Shift bits to postion of outputs                   
                  mov       t2,         outa
                  or        t2,         outsMask
                  xor       t2,         t1
                  xor       outa,       t2
    

                  waitpeq   startState, waitMask
                  mov       t1,         ina                 'Get the current inputs
                  and       t1,         insMask             'Mask out everything but control inputs
                  shr       t1,         #STP_IN             'Shift bits to low byte
                  shl       t1,         #CLK_OUT            'Shift bits to postion of outputs
                  mov       t2,         outa
                  or        t2,         outsMask
                  xor       t2,         t1
                  xor       outa,       t2
                  
                  jmp       :loop                           'repeat
    

    If I change the enable input signal it ends up wiping out the motor step setting on pins 6,7 and sets the step output high when no step was input.·· Pressing the button for enable again kills my output·to the LCD in another cog.· Same with pressing the step button.· It clears·pins 6 and 7·and it doesn't output the STP_IN --> CLK_OUT·pulse on the output line until the second wait point is tripped.
  • photomankcphotomankc Posts: 943
    edited 2009-12-14 04:01
    SUCESS!!!!! FREAKING SUCESS!!!!!!

    :loop         mov       oldIns,     ina                 'Copy what the inputs were
                  and       oldIns,     insmask             'Mask to just our inputs
                  waitpne   startState, waitMask
                  mov       newIns,     ina  wz             'Get the current inputs
                  and       newIns,     insmask             'Mask to just our inputs
                  xor       oldIns,     newIns              'What changed?
                  shr       oldIns,     #STP_IN
                  shl       oldIns,     #CLK_OUT            'Move what changed into position                  '
                  xor       outa,       oldIns              '
                  
     
                  mov       oldIns,     ina                 'Copy what the inputs were
                  and       oldIns,     insmask             'Mask to just our inputs 
                  waitpeq   startState, waitMask
                  mov       newIns,     ina  wz             'Get the current inputs
                  and       newIns,     insmask             'Mask to just our inputs
                  xor       oldIns,     newIns              'What changed?
                  shr       oldIns,     #STP_IN
                  shl       oldIns,     #CLK_OUT            'Move what changed into position                  '
                  xor       outa,       oldIns               
                  jmp       :loop                           'repeat
    


    Had to use ina exclusively to get ahold of which pins changed.· I kept mixing ina and outa.·Then slide the mask that created up into place against the outputs and do an·XOR to toggle the pin/pins that changed.· Good lord.··
    Holy smokes it's fast though!· Now I'll have to add in the logic to put the direction signal onto the wires first since it has to be present 2us before the clock pulse and then its a matter of adding in the position tracking and other logic.· It works though.


    Post Edited (photomankc) : 12/14/2009 4:10:52 AM GMT
  • kuronekokuroneko Posts: 3,623
    edited 2009-12-14 06:05
    See, you're getting there! Note that your jmp instruction requires a #, otherwise it may go off into nowhere [noparse]:)[/noparse]

    The loop itself could use some cleanup, something like this for example:

    :loop         mov       oldIns,     ina                 'Copy what the inputs were
                  waitpne   startState, waitMask
                  xor       oldIns,     ina                 'What changed?
                  and       oldIns,     insmask             'Mask to just our inputs
    
                  shr       oldIns,     #STP_IN
                  shl       oldIns,     #CLK_OUT            'Move what changed into position
                  xor       outa,       oldIns              ' 
    
    
                  mov       oldIns,     ina                 'Copy what the inputs were
                  waitpeq   startState, waitMask
                  xor       oldIns,     ina                 'What changed?
                  and       oldIns,     insmask             'Mask to just our inputs
    
                  shr       oldIns,     #STP_IN
                  shl       oldIns,     #CLK_OUT            'Move what changed into position
                  xor       outa,       oldIns               
    
                  jmp       #:loop                          'repeat
    
  • photomankcphotomankc Posts: 943
    edited 2009-12-14 07:33
    @StefanL38, Thanks for the hint on PASD. Using that got me to the solution pretty quick. Being able to see what those values were coming out to was key.

    I'll fix the jmp and then work on getting DIR_IN output first. I did some quick tests on the scope. My Spin test app can toggle the STP_IN at about 48KHz and it had no trouble keeping up with that at all. The delay from STP_IN to CLK_OUT is about 380ns! I have a feeling this could hang in approaching 100KHz.

    Thanks for all the helpful info everyone. I feel like I am not stumbling in the dark so badly now. I still would love to see some kind of good building example book or paper come out on it. Would be a big help for the newbs.
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2009-12-14 10:10
    Actually I found the error in my code, the line:

    or        t2,         outsmask            'Mask for output pins only
    
    



    Should be an AND!!!!! I was not masking a thing! I have changed the code above now.

    Glad you got it working though, in changing to ina and thinking about it for yourself you also corrected my error [noparse]:)[/noparse] Should work with outa as well.

    Graham
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-12-14 20:10
    Hello,

    it such a big joy for me yeah.gif to give an impulse that encourages to post code and then see
    how things get explained by the community and make the initial poster drive up the learning curve.

    best regards

    Stefan
Sign In or Register to comment.