Shop OBEX P1 Docs P2 Docs Learn Events
PASM Newbie Questions — Parallax Forums

PASM Newbie Questions

ShawnaShawna Posts: 508
edited 2012-11-01 17:33 in Propeller 1
Hello everyone,
I am pretty new to the prop, but my first micro controller was a basic stamp, and when that no longer fit my needs I moved to Pics and Pic Basic Pro. I dove into the prop to do some embedded web-server projects and got in way over my head and then dropped the project. Winter is about here and that means I am going to be stuck inside so I decided to jump back into the Prop.

What I want to do, is learn PASM so I can write efficient code for the Prop, but I am having problems finding examples that are simple and small building blocks for learning PASM. Does anyone have any links to sites with tutorials? It is kind of hard for me to wrap my head around multi-tasking with the Prop since there is no interrupts. I know that there is 8 Cogs, but the thought process is still different when planning a project.

My first question is, can one pin be changed to an output and turned on and off without affecting the whole 32 bit outa register? I know it can be in spin but I am not sure about in PASM. I read something in the manual about muxing but I did not understand it.

Thanks
Shawn

Comments

  • User NameUser Name Posts: 1,451
    edited 2012-10-07 08:31
    Shawna wrote: »
    My first question is, can one pin be changed to an output and turned on and off without affecting the whole 32 bit outa register?
    Absolutely!

    I always recommend the tutorial Graham Stabler provided.
  • ShawnaShawna Posts: 508
    edited 2012-10-07 08:43
    Thank You User Name,
    That looks like a great place to start.
  • User NameUser Name Posts: 1,451
    edited 2012-10-07 10:20
    You are welcome. There are even simpler discussions of this matter here. This, and many other such discussions, can be found in the sticky links at the top of this forum. Be sure to catch PhiPi's Tricks n Traps there.
  • ShawnaShawna Posts: 508
    edited 2012-10-07 14:25
    Would you guys mind critiquing my first very simple program? All it does is start 2 cogs and blink a seperate led with each. I am not sure how to format the DAT portion of the file. The program seems to function fine but does not look right to me.

    'ASMLED2CogBlink
    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    PUB Main
    cognew(@Blink, 0) 'Launch new cog
    cognew(@Blink2,0) 'Launch new cog
    DAT


    Blink org 0 'Begin at Cog RAM addr 0
    mov S1PinMask, #1 'Mask's selected and sets Direction for only
    shl S1PinMask, SerPin1 'one pin.
    or Dira, S1PinMask


    mov Time, cnt 'Sets up waitcnt delay
    add Time, Delay


    :loop
    or Outa, S1PinMask 'Makes Pin 0 High(ON).


    waitcnt Time, Delay 'Waits until cnt = Time and then adds Delay to Time


    andn Outa, S1PinMask 'Makes Pin 0 Low(OFF).


    waitcnt Time, Delay 'Waits until cnt = Time and then adds Delay to Time


    jmp #:loop 'Jumps to :loop


    SerPin1 long 0
    Delay long 2_000_000 'Clock cycles to delay
    S1PinMask Res 1
    Time Res 1






    Blink2 org 0 'Begin at Cog RAM addr 0
    mov S2PinMask, #1
    shl S2PinMask, SerPin2
    or Dira, S2PinMask


    mov Time1, cnt
    add Time1, Delay1


    :loop
    or Outa, S2PinMask 'Makes Pin 0 High(ON).


    waitcnt Time, Delay


    andn Outa, S2PinMask 'Makes Pin 0 Low(OFF).


    waitcnt Time1, Delay1


    jmp #:loop


    SerPin2 long 1
    Delay1 long 10_000_000 'Clock cycles to delay
    S2PinMask Res 1
    Time1 Res 1


    Thanks
    Shawn
  • ShawnaShawna Posts: 508
    edited 2012-10-07 14:30
  • User NameUser Name Posts: 1,451
    edited 2012-10-07 22:37
    Shawna wrote: »
    I am not sure how to format the DAT portion of the file. The program seems to function fine but does not look right to me.

    Not sure about anyone else, but I would put a second DAT on the line above Blink2. At least in Prop Tool, it aids readability to separate PASM code destined for different COGs. You might also be more generous with tabbing...in anticipation of adding assembly conditions and effects.
  • edited 2012-10-08 15:29
    Here are links to two articles that shed some light on assembly. I have found them both to be very helpful.
    PASM tutorial by DeSilva
    Assembly Language Primer for the Absolute Beginner by Doug Dingus (potatohead)

    The following discussion threads might be helpful as well:
    Assembly step by step
    Propeller Assembly for Beginners
    Propeller Resource Index
    Machine Language Tutorial
    Assembly Examples for the Beginners

    Sandy
  • edited 2012-10-08 15:59
    Oh, almost forgot. To post code and have the formatting retained use the code and /code tags to enclose your code as follows:

    {code}
    Some Code Here
    {/code}

    i've used curly brackets above to show the structure. Here it is with the square braces [ and ].
    Some Code Here
    

    Sandy
  • frank freedmanfrank freedman Posts: 1,983
    edited 2012-10-08 16:11
    Here are links to two articles that shed some light on assembly. I have found them both to be very helpful.
    PASM tutorial by DeSilva
    Assembly Language Primer for the Absolute Beginner by Doug Dingus (potatohead)

    The following discussion threads might be helpful as well:
    Assembly step by step
    Propeller Assembly for Beginners
    Propeller Resource Index
    Machine Language Tutorial
    Assembly Examples for the Beginners

    Sandy

    {/Edit Oops, did not see it in the listing...... Prop Asm for Beginners is in the list......} which contains some really great contributions with supporting examples from some of the most knowledgeable members of the forum. Just remember to filter out the backscatter behind the initial purpose of the thread. Some of the best parts concerned passing info from hub to cogs and back. Mux and logicals also got good coverage here. Pay special attention to the names Kuroneko, Heater, Jazzed, Jonnymac, potatohead, and others. Some really great explanations are presented.
  • ShawnaShawna Posts: 508
    edited 2012-10-09 14:30
    Thanks guys I thought maybe I should put another DAT but I was not sure.
  • User NameUser Name Posts: 1,451
    edited 2012-10-09 15:53
    Shawna wrote: »
    Thanks guys I thought maybe I should put another DAT but I was not sure.
    If this was your first real effort with PASM, you're doing great!
  • ShawnaShawna Posts: 508
    edited 2012-10-13 16:25
    Hey guys,

    I am trying to translate this simple spin code into PASM. The prop tool says it is only 7 longs. I cannot for the life of me accomplish this in 7 longs, can someone show me what to do. I only ask because I am sure someone, with experience can do this without even thinking about.
    CON
            _xinfreq = 5_000_000                     ' 5 MHz external crystal 
            _clkmode = xtal1 + pll16x                ' 5 MHz crystal multiplied → 80 MHz
    VAR
    PUB ServoInput
      dira[0]    := 1                            
      dira[21]  := 0                            
    Repeat
        outa[0] := ina[21]
    

    Thanks
    Shawn
  • Mike GreenMike Green Posts: 23,101
    edited 2012-10-13 16:51
    DAT
                    org   0
    ServoInput or    dira,outputMask   ' dira[0] := 1
                andn  dira,inputMask   ' dira[21] := 0
    :loopHere  test  inputMask,ina   wc   ' ina[21] to carry bit
                    muxc  outa,outputMask   ' carry bit to outa[0]
                    jmp   #:loopHere   ' repeat above
    
    inputMask  long  1<<21   ' bit 21 mask
    outputMask long  1<<0   ' bit 0 mask
    
    This will need something to start up the PASM code like a COGNEW.
  • ShawnaShawna Posts: 508
    edited 2012-10-16 14:39
    Thanks Mike,
    Actually I can not get your code to work but I am still playing with it. There are allot of little pieces in there that I need to figure out. It is very helpful.
    Thanks
    Shawn
  • ShawnaShawna Posts: 508
    edited 2012-10-16 14:53
    Ok, scratch that I got it working, I messed something up in my cognew command.
    Does this program have two cogs running? And if it does what are the consequences of me stopping the cog 0. Will the cog running the PASM (ServoInput) still run? I'm not sure why one would do that, but I am just trying to learn. It seems to me that once the DAT portion is running there is no need to run the spin COG.
    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    PUB Main
    cognew(@ServoInput, 0) 'Launch new cog
    DAT
                    
    ServoInput    org   0
                  or    dira,outputMask      ' dira[0] := 1
                  andn  dira,inputMask       ' dira[21] := 0
    :loopHere     test  inputMask,ina   wc   ' ina[21] to carry bit
                  muxc  outa,outputMask      ' carry bit to outa[0]
                  jmp   #:loopHere           ' repeat above
    
    
    inputMask  long  1<<21   ' bit 21 mask
    outputMask long  1<<0    ' bit 0 mask
    

    This program is 11 longs. Still more than the Spin program I posted. Is that because of the overhead to start the second COG?

    Thanks
    Shawn
  • Mark_TMark_T Posts: 1,981
    edited 2012-10-16 16:41
    Yes, that's right I think. The start cog has exited and is now idle, but the ServoInput cog will still be running. Note that when a cog starts all special registers (except PAR, INA, CNT I believe) are zero, so you can assume DIRA is all zero.

    If you use BST (Brads Spin Tool) it has a compile-listing window you can pop up to see all the gory details of the compiler output.
  • ShawnaShawna Posts: 508
    edited 2012-10-29 11:44
    Hey guys,
    Thanks for all of your help, this has been fun learning PASM. I got another question. Is LMM written in PropBasic really 4 to 5 times faster in execution time than spin? I need to do some simple multiplication and division and it just takes to long in spin, so I was kicking around the idea of doing it in PASM. Thats when I discovered PropBasic. If it is really 4 to 5 times faster than Spin, I could probably deal with that. I have this dream though, to write most of this program in PASM. Based on the size of the object library for spin I would assume most people do not use PropBasic. And after reading a few threads on PropBasic I am not sure that it is even finished, but looks very impressive. So what are your guys thoughts. Is PropBasic better than spin? The only disadvantage I can see with PropBasic is that the code may be a little more bloated than spin. Also I am thinking that if I want to write 75 percent of my code in PASM, PropBasic may be a good way of executing my PASM.
    Thanks
    Shawn
  • JasonDorieJasonDorie Posts: 1,930
    edited 2012-10-29 12:09
    Shawna wrote: »
    I need to do some simple multiplication and division and it just takes too long in spin, so I was kicking around the idea of doing it in PASM.

    While I'd never try to convince someone NOT to learn PASM (it's really useful), it might not be necessary to learn it just to get your code to go faster. Can you post the code you're referring to here? The Spin compiler makes absolutely no attempt at optimization, so it's possible that you have things in your code that are slowing it down. It's also possible you don't, but it's worth looking at.
  • tonyp12tonyp12 Posts: 1,951
    edited 2012-10-29 12:55
    >manual about muxing but I did not understand it.
    muxz-muxc only works if you have a prior test conidtion that sets z or c
    even then it may be easier to understand by using two lines to emulate the mux instruction like this

    -test something- wz
    if_z or outa, pin21
    if_nz andn outa, pin21
  • ShawnaShawna Posts: 508
    edited 2012-10-30 10:05
    Ok, I wrote a small code to read 8 variables from hub into 8 local variables. Then the program divides each local variable by a number and writes them back to the hub in their original locations. I wrote this code in PropBasic, and spin. In spin the code takes 285uS, in PropBasic in PASM mode it takes 85uS, and in PropBasic in LMM mode it takes 485uS.

    My brain is stuck in and endless loop.

    My ultimate goal is to make a quadcopter controller. I know there is already code out there for this, but I want to try writing the code myself. I want to learn PASM and Spin while I am doing this and I also want to understand every line of code in the program so I can tweak stuff and modify it as needed. I have found that just taking objects from the library doesn't really help me learn much. Also as soon as I run into something that I want to do that is not in the object library I am screwed.

    So I am taking one part of the quadcopter program at a time and learning how to write it. I have the rc_input signal and the servo_output signal parts of the code working. I will admit I highjacked the servo32 code for this but not until I fully understood it. Once I figured out how the code functioned then I tore it apart and modified it for what I needed.

    I would like my entire control loop for my flight controller to take no more than 2.5mS. This would give me a refresh rate of 400hz. There is no point in the refresh rate being any faster because this is all the faster I can refresh my esc motor controllers. This is why I keep harping on the speed of code execution. There are algorithms for mixing data from the gyros and other sensors that take a little bit of math, and I want to do this as fast as possible.

    I am kicking around the Idea of having a cog running all the time just to do math functions but I have not researched this enough to know if this is possible.

    Anyways, my brain is still stuck in an endless loop. Maybe I will move to another part of the quadcopter code. I need to get an I2C bus up and running at 400Khz.

    I really like the PropBasic, but the code is awfully bloated and the 2k cog space is very limited, but it is fast as hell. LMM is cool but to slow, seems to be slower than spin.

    Can anyone hit my reset button?
    Thanks
  • JasonDorieJasonDorie Posts: 1,930
    edited 2012-10-30 14:09
    I've managed to get mine to 250Hz (with a little bit of room to spare) using just Spin for the core loop, including the PIDs. If the PID code were moved into PASM it'd almost certainly be more than 2x faster, well within your 400Hz requirement.

    If you want a COG to act as a co-processor for the math, take a look at how Float32 works. It has a Spin interface that sets hub variables for the arguments being passed. A COG routine sees a specific value in a HUB location that triggers a command to execute, it fires the appropriate function and returns the result. You could do something similar where you passed the address of the first of your 8 values to the COG. The PASM code would then read the values from the hub, do the math on them, generate results, then write the results back out to the hub locations (or others, possibly, to avoid problems with other code that might be using those values).

    The individual functions in the Float32 code are complicated, but the way it works isn't, and it might give you a head start on how to set up your own code. From there you'd need multiply or divide functions and the glue code to tie it all together. It'll take some time to get right, but working in small pieces will make it much easier.

    For I2C stuff, I'd suggest starting with Mike Green's basic I2C driver, as there's a Spin version and a PASM version, both of which are well documented. This is what I started with when writing my gyro / accel code.

    http://obex.parallax.com/objects/672/ (Spin)
    http://obex.parallax.com/objects/611/ (PASM)

    Have fun with it! I'm looking forward to seeing your progress.
  • ersmithersmith Posts: 6,054
    edited 2012-10-30 17:59
    Generally speaking LMM code will be faster than Spin, so I'm a bit surprised by your results. PropBasic is a good compiler, but perhaps it has a blind spot when it comes to math functions in LMM mode. In general I've found that the times run: PASM < compiled Cog code < compiled LMM code < compiled and interpreted code (with Spin being in the last category).

    If speed rather than size is the primary issue, then it would be worth looking into C, or perhaps using spin2cpp to convert your Spin code to C++ and then compiling it with PropGCC. This is particularly effective for compute intensive code -- for example, Heater's FFT benchmark runs in 1465 ms in Spin, but speeds up to 135 ms when that same Spin code is compiled with "spin2cpp --elf -O2 -o fft.elf fft_bench.spin". (This compares to 47 ms for the pure C version and 25 ms for the PASM version.)

    Eric
  • ShawnaShawna Posts: 508
    edited 2012-10-31 14:26
    So it turns out I am not very good at SPIN either. I tried to write a short program to write a byte into a 24lc256 eeprom, and then read it back out and display the value on cpu. I have pins 1-4 of the eeprom tied to gnd. SDA line is tied to P27 and SCL is tied to P26. WP is tied to GND and VCC is tied to 3.3v. When I read the variable frequency out I get a -1 value. I have tried this with pull ups(10K) without pull ups. I am using the Basic_I2C_Driver_1 object and the Parallax Serial Terminal object. Can you guys look at my code and tell me if you see anything obvious. I am stumped.

    Should I move my spin questions to another post since the title of this is PASM Newbie Questions?
    Thanks

    CON
    
        _xinfreq = 5_000_000                     ' 5 MHz external crystal 
        _clkmode = xtal1 + pll16x                ' 5 MHz crystal multiplied &#8594; 80 MHz
    
    
    OBJ
       
      PST : "Parallax Serial Terminal"
      I2C : "Basic_I2C_Driver_1"
       
    VAR
      Long Frequency   
    PUB Main | variable
      waitcnt(clkfreq*5+cnt)
      Frequency := 10
      variable := 134
      PST.Start(250_000)
      PST.Str(String("I2C Test 0 "))
      I2C.Initialize(26)
      I2C.Start(26)
      I2C.WriteByte(26, $7000, 0, variable)
      I2C.Stop(26)
      I2C.Start(26)
      Frequency:= I2C.ReadByte(26, $7000, 0)
      I2C.Stop(26)
      PST.Dec(Frequency)
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-11-01 03:22
    Separate start/stop calls are not necessary when you use the byte transfer functions. Also, you parameters are slightly wrong. Try this:
    CON
      _clkmode = XTAL1|PLL16X
      _xinfreq = 5_000_000
    
    CON
      SCL = 26
    
    OBJ
      PST : "Parallax Serial Terminal"
      I2C : "Basic_I2C_Driver"
       
    VAR
      long Frequency   
    
    PUB Main | variable
    
      PST.Start(115_200)
      waitcnt(clkfreq*3 + cnt)
    
      Frequency := 10
      variable := 42
      PST.Str(String("I2C Test 0 "))
    
      I2C.Initialize(SCL)
      I2C.WriteByte(SCL, I2C#EEPROM, $7000, variable)
      repeat while I2C.WriteWait(SCL, I2C#EEPROM, $7000)
    
      Frequency:= I2C.ReadByte(SCL, I2C#EEPROM, $7000)
      PST.Dec(Frequency)
      PST.Char(13)
    
  • ShawnaShawna Posts: 508
    edited 2012-11-01 17:33
    kuroneko, thank you
    I forgot about the 5mS write time, among other things I have some more questions but not enough time to ask.
Sign In or Register to comment.