Shop OBEX P1 Docs P2 Docs Learn Events
I need help with assembly lanugage for my senior project — Parallax Forums

I need help with assembly lanugage for my senior project

BKotBKot Posts: 5
edited 2011-04-04 17:47 in Propeller 1
Hello Everyone,
This is my first post on the parallax forum and I am trying to get my senior project working by April 16 for the IEEE student activities conference. My partner and I are building a micromouse and we chose to use the propeller as our processor. We initially used spin but the code was not executing fast enough for our needs. I am now trying to re write all of our codes into assembly in the next two weeks but I still can't figure out how to pass values from one cogs assembly code to another cog. The first cog reads serial signal from two AD converters and the second cog will be in charge of driving straight.

Can someone write a simple example of how to pass this information? I have thoroughly skimmed over "Programming the Parallax Propeller using Machine Language" and searched through the forum for the past week with no success on this particular subject (I am bad at searching through forums). I now the information is out there in numerous places but cant seem to find any of those places. Any help would be greatly appreciated as my partner and I are on a narrowing deadline.

I also dont understand the purpose or advantage of objects. Though I would prefer not to use objects to retain understanding of my current code, can someone still elaborate on them for me?

Comments

  • SSteveSSteve Posts: 808
    edited 2011-04-02 18:54
    Cogs can't read or write each other's RAM. You'll need to pass information through hub RAM.

    Also, you'll find that people on this forum are very helpful, but there's a general expectation that you show some effort before asking others to start doing work for you. This is much more of a "teach a person to fish" rather than "give a person a fish" community.
  • KyeKye Posts: 2,200
    edited 2011-04-02 19:07
    Just overclock your prop. If your at 100Mhz you may be fast enough.

    If not, rewriting everything in ASM will be very hard in a few days.
  • martinhmartinh Posts: 58
    edited 2011-04-02 19:11
    I agree to what SSteve said, but also want to give some hint that might make the live for you easier. Without experience, distributing a larger spin program into pasm running in different cogs and establish communication via hub ram or serial communication via pins can be quite challanging. So depending on the speed you really need an intermediate approach may work.
    There are languages for the prop available which compile to code much faster than spin but slower than pasm. If a speedup by a factor of 4-5 is good enough for your project it might be easier to code it in C and use the catalina C compiler or to code it in basic and use the propbasic compiler.
    What you save is the complexity to introduce some IPC for the cogs.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-02 19:34
    Can someone write a simple example of how to pass this information?

    You can pick some common locations at the top of hub ram, and each cog can write or read to those locations. Start at $7FFF and work down.

    Or you could create a variable in your main spin program, then pass the location of that variable to each cog using PAR when you start the cog. You can also pass the location of an array. This method has the advantage that both cogs and spin have access to the variable.
    I also dont understand the purpose or advantage of objects.
    I agree. I could write pages on why I agree, but it might cause an endless debate here and distract from your immediate task which is to get something working in a limited amount of time.

    What works well on this forum is to post some code fragments and ask a simple question. The forum works 24/7 and I've had answers sometimes within a few minutes, often to questions that are hard to find in the manual.

    Any chance you could post what code you have? (warts and all, that is ok!)
  • JonnyMacJonnyMac Posts: 9,233
    edited 2011-04-02 19:59
  • BKotBKot Posts: 5
    edited 2011-04-02 20:39
    I need to get the RSenVal and LSenVal values copied into the main memory so 2 additional cogs can continuously copy the values into their ram. These variables are near the bottom of the second DAT file above the subroutine called CKFollow. I am still in the process of writing the driving software for the two motor controllers.

    Here is the portion of the code I have written so far. I already know I could simplify it to be much faster but that is not my current priority. The clock is already set for 80 MHz in the CON section.
     
     
    '---------------------------------------------------------------------------------------------------  
    VAR
      Word PushButton
    '----------------------------------------------------------------------------------------------------  
    PUB IR_Sensors
      Dira[4]~                                      'This portion of the code prevents the program   
      Repeat                                        ' from starting until an external button is pushed 
        PushButton := INA[4]                        ' on the top of the micromouse, allowin the user to
      While PushButton < 1                          ' center the robot in the starting corner of the maze 
      Waitcnt(clkfreq + cnt)
      Cognew(@ADCclock,0)                           'Cog to run the clock for the AD converter
      Cognew(@SerIn,1000)                           'Cog to read the Serial outputs from 2 ADC0831 converters
      'Cognew(@Motor,2000)                          'Cog used to run steering and basic motion
    '---------------------------------------------------------------------------------------------------------  
    DAT
                  ORG       0
    ADCclock      MOV       DIRA,ClockPinout        'Toggles pins 16 and 23 high and low at 100KHz
    CLKLoop       MOV       OUTA,ClockPinout        '  to create clock signal for the ADCs
                  CALL      #ClkDelay
                  NOP                               'Keeps the signal at a 50% duty cycle 
                  NOP
                  MOV       OUTA, #0
                  CALL      #ClkDelay
                  JMP       #CLKLoop
     
    ClkDelay      Mov       DelayVal,#46            'Subroutine used to generate the delay between 
    DelayLoop     SUB       DelayVal,#1             ' high and low cycles.
                  TJNZ      DelayVal,#DelayLoop
    ClkDelay_RET  RET
    DelayVal      LONG      0                      'Variable for creating the delay to reach 100KHz
    ClockPinout   LONG      $810000                'Activates pins 16 and 23 for clock signal
    '-----------------------------------------------------------------------------------------------              
    DAT
                  ORG       0                      'First part of the code reads the first  
    SerIn         MOV       DIRA,IRMask            '  five bits of the Right Sensor ADC
                  MOV       OUTA,IRMask
    SerLoop       MOV       OUTA,LBReadMask        'CK enable for the first adc 
                  CALL      #CKFollow
                  CALL      #CKFollow              
                  MOV       RRange,INA              
                  AND       RRange,DATMaskR              
                  ROL       RRange,#1
                  CALL      #CKFollow              
                  MOV       RRange,INA              
                  AND       RRange,DATMaskR              
                  ROL       RRange,#1
                  CALL      #CKFollow              
                  MOV       RRange,INA              
                  AND       RRange,DATMaskR              
                  ROL       RRange,#1
                  CALL      #CKFollow              
                  MOV       RRange,INA              
                  AND       RRange,DATMaskR              
                  ROL       RRange,#1
                  CALL      #CKFollow              
                  MOV       RRange,INA              
                  AND       RRange,DATMaskR              
                  ROL       RRange,#1
                  CALL      #CKFollow
                  CALL      #CKFollow
                  CALL      #CKFollow
                  CALL      #CKFollow
                  MOV       OUTA,RBReadMask       'This remaining part of the code reads 
                  CALL      #CKFollow             '  the first five bits of the Left sensor
                  CALL      #CKFollow             '   second ADC
                  MOV       LRange,INA
                  AND       LRange,DATMaskL
                  ROL       LRange,#1
                  CALL      #CKFollow
                  MOV       LRange,INA
                  AND       LRange,DATMaskL
                  ROL       LRange,#1
                  CALL      #CKFollow
                  MOV       LRange,INA
                  AND       LRange,DATMaskL
                  ROL       LRange,#1
                  CALL      #CKFollow
                  MOV       LRange,INA
                  AND       LRange,DATMaskL
                  ROL       LRange,#1
                  CALL      #CKFollow
                  MOV       LRange,INA
                  AND       LRange,DATMaskL
                  ROL       LRange,#1
                  CALL      #CKFollow
                  CALL      #CKFollow
                  CALL      #CKFollow
                  CALL      #CKFollow
                  MOV       DIRA,IRMask
                  MOV       RSenVal,RRange           'Stores final range values into variables  
                  MOV       LSenVal,LRange           '  that will remain consistent through the        
                  JMP       #SerLoop                 '  sampling period.
     
    CKFollow      
    CKHigh        MOV       CLKMask,CKMask           'This Subroutine makes this cog wait
                  AND       CLKMask,INA              '  unil the clock cog completes one 
                  TJZ       CLKMask,#CKHigh          '  oscillation before sampling a bit
    CKLow         MOV       CLKMask,CKMask
                  AND       CLKMask,INA
                  TJNZ      CLKMask,#CKLow
    CKFollow_RET  RET
     
    LBReadMask    LONG      $40000
    RBReadMask    LONG      $80000
    IRMask        LONG      $C0000
    CKMask        LONG      $400000
    CLKMask       LONG      $400000
    DATMaskR      LONG      $4000
    DATMaskL      LONG      $8000
    RRange        LONG      0
    LRange        LONG      0
    RSenVal       LONG      0
    LSenVal       LONG      0
    '--------------------------------------------------------------------------------------
    {DAT
                  ORG       0
    Motor
    MotorStart
    GoStraight                                    'Straight
     
                  JMP       #MotorStart            
    TurnLeft      MOV       OUTA,TLeftPins        'Turn Left
                  MOV       X,LeftDelay
                  CALL      #MovDel
                  JMP       #MotorStart
    TurnRight     MOV       OUTA,TRightPins       'Turn Right
                  MOV       X,RightDelay
                  CALL      #MovDel                                            
                  JMP       #MotorStart
    TurnLeft      MOV       OUTA,TLeftPins        'Turn 180 degrees
                  MOV       X,RotateDelay
                  CALL      #MovDel                                              
                  JMP       #MotorStart
     
    MovDel        SUB       X,#1
                  TJNZ      #MovementDelay
    MovDel_RET    RET
     
     
    X             WORD      0
    StraightDelay WORD      0                                    
    LeftDelay     WORD      0
    RightDelay    WORD      0
    RotateDelay   WORD      0
    LeftSenVal    LONG      0
    RightSenVal   LONG      0
    TRightPins    LONG      %0110
    TLeftPins     LONG      %1001
    ForMainPins   LONG      %0101               }
    
    I saw an example of bringing a global variable into ram by using MOV X, par but I could not find the location in the dat file where one of the global variable was actually copied to the local variable. Do I also have to make a comment when initializing a cog that lists the variable being passed into its ram?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-02 21:40
    That is a great article by Jonnymac.

    This is a very brief note in pseudo code and for one variable
    1) create a variable in the main program "myvariable" or in a var section of the main program
    2) when starting the cog, make the second parameter "@myvariable". This passes the location of myvariable in hub to the cog - this location may change each time you edit your main program. (It does not pass the value of myvariable, only the location)
    3) In the cog startup code, MOV cogvariable,par
    4) use rdlong and wrlong to move data to and from this location in hub, noting the source/destination order of rdlong vs wrlong. See Jonnymac's article near the bottom.
  • Heater.Heater. Posts: 21,230
    edited 2011-04-02 22:42
    Welcome to the forum BKot,
    My partner and I are building a micromouse and we chose to use the propeller as our processor. We initially used spin but the code was not executing fast enough for our needs. I am now trying to re write all of our codes into assembly in the next two week

    Given that a micromouse is a mechanical device we might be surprised that it cannot be controlled fast enough in Spin. But without knowing more about the aims of your project and it's actual code we can only offer general advice on speeding things up.

    It is in the nature of most programs that there is a bottle neck somewhere. That is to say that there might be only one part of your code that is critical and causing major performance loss.

    In that case there is no point rewriting all of your code in PASM or otherwise optimizing it. You may only need to speed up some small critical part some where.

    If 90% of your time were spent in only 10% of the code then obviously speeding up that 10% has a much bigger effect, the other 90% can remain "as is".

    So the trick might be to identify where that critical 10% is in your code. and concentrate optimization efforts on that. Avoid "premature optimization" as they say.

    After all if your code works now but the time taken to rewrite and debug it in PASM takes you passed your project deadline that's not a very good optimization.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-03 01:21
    If you still have the Spin version of the code please post it - the Spin compiler makes no attempt to optimize, so there may be things in your original code which can be greatly improved by knowing a little about how the compiler treats various statements, or with small algorithmic changes. I've had a couple programs I was able to double in speed by making changes to how the code was written, but not having to change what it did.

    As a simple example, constant folding: most compilers will optimize constant portions of an expression, like this:

    X := Y * (80_000_000 / 1000) ' X = y milliseconds

    The Spin compiler will evaluate that expression completely at runtime, unless you tell it not to, like this:

    X := Y * constant(80_000_000 / 1000) ' X = y milliseconds
  • max72max72 Posts: 1,155
    edited 2011-04-03 01:44
    Welcome to the forum.
    Just a couple of possibilities:
    1- rewrite it in propbasic. It creates assembly code, so you'll be blazing fast.
    2- optimize and speed up the critical parts as suggested by Humanoido. After finding bottlenecks, in case spin is not fast enough you could:
    2a- use assembly code as a kind of coprocessor (check float objects as example)
    2b- use spinlmm or inline assembly (both in the obex)

    Massimo
  • RS_JimRS_Jim Posts: 1,773
    edited 2011-04-03 06:26
    Welcome to the forum. I had the same problem with asm for a long time and finally pleaded for help herehttp://forums.parallax.com/showthread.php?128922-Passing-Memory-Address-I-am-stumped!&highlight=Variables. Jonnymac's etimer code toward the end (V2) shows setting up global variables and passing them to/from an ASM cog. I am now successfully using that knowledge to pass that information to several cogs and sharing the output data of my cogs with several more. I can call that my AH-HA moment. Good luck on the senior project.
    RS_Jim
  • BKotBKot Posts: 5
    edited 2011-04-03 10:06
    I would like to thank everyone for your help. I wrote a little test program to pass the value of a push button from one cog to the hub ram and copy that value to another cog. It works but there is a slight delay between the first LED and second LED.
    CON
      _clkmode = xtal1 + pll16x  'Use crystal*8 for a speed of 40_000_000 Hz
      _xinfreq = 5_000_000       'External 5 MHz crystal XI & XO
                                 'Instructons summary on page 40 of TM
    '------------------------------------------------------------------------------
    VAR
      LONG  SHARED
    '---------------------------------------------------------------------------  
    PUB Micromouse_Assembly_PBLED
      cognew(@PButtonLED,@SHARED)
      cognew(@OUTPUT,@SHARED)
    '---------------------------------------------------------------------------
    DAT
                  ORG       0
    PButtonLED    MOV       GlobalStore,PAR
                  MOV       DIRA,BVal
    LittleLoop    MOV       BPIN,INA            'Check Value of Push Button
                  ADD       GlobalStore,#1
                  NOP          
                  AND       BPIN,CMask
                  WRLONG    BPIN,GlobalStore     'Copies value to HUB Ram
                  MOV       OUTA,#0   
                  TJZ       BPIN,#NLGHT
                  MOV       OUTA,BVal         'Turn LED1 on if Push Button is on  
    NLGHT         JMP       #LittleLoop
     
     
     
    BVal          LONG      %100_0000
    BPIN          LONG      0
    CMask         LONG      %1_0000
    GlobalStore   LONG      0
    '---------------------------------------------------------------------------
    DAT
                  ORG       0
    OUTPUT        MOV       GlobalStore2,PAR
                  ADD       GlobalStore2,#1
                  MOV       DIRA,PINL
    OLoop         RDLONG    PINVal,GlobalStore2     'Read Value from hub ram
                  ROL       PINVal,#3
                  MOV       OUTA,PINVal              'Use Value to light LED2 
                  JMP       #OLoop
     
    PINVal        LONG      0
    PINL          LONG      %1000_0000
    GlobalStore2  LONG      0                       
    
  • RS_JimRS_Jim Posts: 1,773
    edited 2011-04-04 17:47
    looks like that will work, but I question why you are writing your pinvalue information to par+1. that offsets your data from the base long by 1 byte.
    if you really want your data in your global var "shared" you should do your wrlong back to par or globalstore unmodified.
    RS_Jim
Sign In or Register to comment.