Propeller Assembly for beginners

2456729

Comments

  • edited July 2011 Posts: 539Vote Up0Vote Down
    Thanks Heater

    The following code alternates the LEDs on lines 0 and 1
    It works (with your input)
    What I want to know is, Is this the right way to do it for beginners
    Also tell me what you mean by code tags.

    con
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    pub main
    cognew(@toggle, 0)

    dat
    org 0
    toggle mov dira, pin
    mov time, cnt
    add time, #9

    :loop waitcnt time, delay
    mov outa, pin2

    waitcnt time, delay
    mov outa, pin3

    jmp #:loop

    pin long %00000000_00000000_00000011
    pin2 long %00000000_00000000_00000010
    pin3 long %00000000_00000000_00000001
    delay long 10_000_000
    time res 1
  • edited July 2011 Posts: 0Vote Up0Vote Down
    A general rule is not to use mov on outa as it will also turn off all other pins that this cog have as outputs in dira.

    or ' turn pin high

    1100 'current state for example
    0010 ' ora this value
    1110 ' result


    andn 'turn pin low

    1110 'current state for example
    1101 ' and this value, this would be the bit negative value of pin so that's the reason to use andN to save you from declearing a not version
    1100 ' result

    xor 'toggle pin.

    use [ c o d e ] and [ / c o d e] without space in your postings.

    You only show 24 bits in pin, to be correct you should have 4 * 8bits
    or use: 1<<pin# (or also: |<pin#)

    could also use (to get rid of the pin _00000011)
    mov dira,pin2
    or dira,pin3

    or at least call it 'myoutputs"
    and the other pin1 and pin 2
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Tony:

    Looking at just the loop

    :loop waitcnt time, delay
    mov outa, %01
    waitcnt time, delay
    xor outa, %11
    jmp #:loop

    This works but I really don't know why because I have tried a bunch of other
    ways of doing it and they work too. I don't understand them either. Could you
    write this loop for me exactly the way is should be with comments.

    Harprit.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    There are many ways to get the same end result.
    But it's always good to learn coding in the 'correct way' so the code can be easily expanded.

    I toggle two leds here, I would not say the code is in a correct way. (click see more to see the source code)
    http://www.youtube.com/watch?v=_5zRxYyfDN0
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Using "MOV OUTA, value" is fine as long as the COG only drives a known set of outputs.

    There are advantages in some cases and hazards in others. One of the more interesting instructions is "RDBYTE OUT, ptr". Often if a signal such as write enable WE* needs to be driven in addition to P0..P7, DIRA can be set to drive WE* at the same time. A pull up can be used for making WE* high with DIRA setting it to an input which allows other operations such as read.

    Using "OR OUTA, value" and "ANDN OUTA, value" certainly have their place when complicated COG IO is being used. Very often however the instructions mentioned along with other operations on the bus can slow things down.
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Tony. Could not get to your code
    Jazzed. Your note was over my head.

    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Harprit wrote: »
    Also tell me what you mean by code tags.
    Simply put [noparse]
    [/noparse][/b] in front of your code block and [B][noparse]
    
    [/noparse] at the end. Example:
    :loop   waitcnt time, delay
            xor     outa, #%11             ' toggles bits 0 and 1
            jmp     #:loop
    
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Thank you kuroneko.

    That really captured the essence of it and made me see it in a flash
    And yes of course I knew that, but I could not see it for the life of me and
    you made it so clear. I hope I can transfer such clarity to the readers in
    the text.

    Harprit.
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Here is the next batch, there is still a lot of editing to do and the figures are not in place
    The two LEDs to to lines 0 and 1

    Change the program so that it looks like the following:
    con
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    
    pub main
    cognew(@toggle, 0)
    
    dat
           org      0                      'start of the program storage locations
    toggle mov      dira,   pin            'pin now sets lines 0 and 1 as outputs
           mov      time,   cnt            'sets the delay time to 10m cycles
           add      time,   #9             'adds 9 to the time count
    
    :loop  waitcnt  time,   delay          'the wait instruction
           mov      outa,   pin0on         'sets output 0 on and 1 off
    
           waitcnt  time,   delay          'the wait instruction 
           mov      outa,   pin1on         'sets output 1 on and 0 off
    
           jmp      #:loop                 'go back and loop.
    
    pin      long %00000000_00000000_00000000_00000011    'used to set 0 and 1 as outputs
    kine0on  long %00000000_00000000_00000000_00000001    'used to turn on line 0
    line1on  long %00000000_00000000_00000000_00000010    'used to turn on line 1
    delay    long 10_000_000                              'delay cycles defined
    time  res  1                                          'storage location for time
    
    Program XXX
    Blinking lines alternately.

    The above program XXX will blink the LEDs on lines 0 and 1 on and off alternately. This code is easy to read but it is archaic and it is not the best way to do it. An only slightly better way to write this program is shown next in Program XXX. Again the changes are to the looped part of the program
    con
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    
    pub main
    cognew(@toggle, 0)
    
    dat
           org      0                      'start of the program storage locations
    toggle mov      dira,   pin            'pin now sets lines 0 and 1 as outputs
           mov      time,   cnt            'sets the delay time to 10m cycles
           add      time,   #9             'adds 9 to the time count
    
    :loop  waitcnt  time,   delay          'the wait instruction
           or      outa,   %01             'sets output 0 on and 1 off
    
           waitcnt  time,   delay          'the wait instruction 
           or      outa,   %10             'sets output 1 on and 0 off
           jmp      #:loop                 'go back and loop.
    
    delay    long 10_000_000                              'delay cycles defined
    time  res  1                                          'storage location for time
    
    Program XXX a slightly better way to write program XXX
    Blinking lines 0 and 1 alternately.

    When you run the above program you will see that two LEDS can be turned on and off alternately with the above register assignments. The program shows you how to set the lines as Inputs and Outputs with simple statements and how to affect the I/O operation of the pins. However this is both the tedious and archaic way of doing it. A number of better ways to do it follow. In these examples we are using shorthand notation and binary math techniques to manipulate the registers. Handling registers in this way is important in almost all the things that we will be doing. The techniques we use next use the following principles:

    There are three basic things we can do to one bit in one operation.
    Change it from a low to high-level (0-->1)
    Change it from a high to low-level (1-->0)
    Invert its state, in other words toggle the bit. Make it high if low and low if high.

    Assume that the current 4 bits under consideration are %1010
    We can change any bit in this group to high with the ora operation on that bit.

    1010 current content
    ora 0001 addresses the last bit
    1011 result: the last bit is turned on (changed from 0 to 1)

    If we want to turn a bit off we can do it with the andn operation

    1010 current content
    andn 0010 addresses the third bit
    1000 result: the third bit is turned off (changed from 1 to 0)

    If we want to change (or toggle) the state of a bit we use the xor command

    1010 current content
    xor 0011 addresses the third and fourth bits.
    1001 result: the third and fourth bit are toggled (changed from 1 to 0 and 0 to 1)

    Now let us look at the looping part of the code in our program and see how we can use the above commands to make the LEDS flash alternatively.

    The simplest way is to first set the two bits that control the LEDs to 01 or 10 with the outa command and then do a toggling procedure with the xor command.
    dat
           org      0                   'start of the program storage locations
    toggle mov      dira,   #%11        'pin now sets lines 0 and 1 as outputs
           mov      time,   cnt         'sets the delay time to 10m cycles
           add      time,   #20         'adds 12 to the time count
           mov      outa,   #%01        'sets the two bits 
    :loop  waitcnt  time,   delay
           xor      outa,   #%11        'toggles bits 0 and 1
           jmp      #:loop 
    
    Now that we understand the simplest of bit manipulations and the creation of the simplest of loops. Let us expand on these idea to learn how to undertake some other often used techniques.


    Shifting the bits in a register left and right.

    The two instructions used to shift bits left and right are SHL and SHR. Bits can be shifted from 1 to 32 places within the 32 bit registers.

    If we use a bit shifting technique to move the ON bit back and forth to alternate the coming on of the two bits we have been considering above, the data part of program would look like the listing shown in Program XXX. Here we have to wait after each shift to duplicate the effect in program XXX above.
    dat
           org      0                   'start of the program storage locations
    toggle mov      dira,   #%11        'pin now sets lines 0 and 1 as outputs
           mov      time,   cnt         'sets the delay time to 10m cycles
           add      time,   #20         'adds 12 to the time count
           mov      outa,   #%01        'sets the two bits 
    :loop  waitcnt  time,   delay       'delay
           shl      outa,   #%1         'shift left one bit
           waitcnt  time,   delay       'delay
           shr      outa,   #%1         'shift back right one bit
           jmp      #:loop 
    
    Program XXX
    Controlling off the LEDs by shifting the active bit left and right.




    Creating Subroutines/Methods

    PASM has the waitcnt command for creating pauses but we are going to ignore that in the immediate discussion.

    First let us see how we call a subroutine in PASM. We will make the wait a part of a subroutine and then call the subroutine whenever we need to wait. This needs to be done after each shift command. The complete code for this is
    con
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    
    pub main
    cognew(@toggle, 0)
    
    dat
           org      0                   'start of the program storage locations
    toggle mov      dira,   #%11        'pin now sets lines 0 and 1 as outputs
           mov      time,   cnt         'sets the delay time to 10m cycles
           add      time,   #200        'adds 12 to the time count
           mov      outa,   #%01        'sets the two bits 
    :loop
           call     #clkdelay           'call the delay subroutine
           shl      outa,   #%1         'shift left one bit
           call     #clkdelay           'call the delay subroutine
           shr      outa,   #%1         'shift back right one bit
           jmp      #:loop
           
    clkdelay  waitcnt time, delay       'the delay subroutine
    clkdelay_ret    ret                 'return for delay subroutine
    
    delay      long 10_000_000          'delay cycles defined
    time       res  1                   'location for time
    
    Program XXX
    Places the waitcnt command in a subroutine.

    Often we need to be able to do something a fixed number of times and then do something else. In order to do this we need to learn how to set up counters. Let us use a counter that uses waits of one quarter (0.25 seconds) repeatedly to make up the delays we need in our programs from time to time. The wait period will need to run through 80_000_000_/4 cycles of an empty loop before exiting. We will then place this method in our blink routine to make sure it works.

    Again: our clock is running at 80 MHz, so one second takes 80_000_000 cycles and 0.25 seconds take 20_000_000 cycles. We also know that the average instruction takes 4 clock cycles. So our 0.25 second subroutine has to have 5_000_000 iterations through its loop.(Our counts are not exact because we are not counting every instruction but it will be close enough for what we are trying to learn at this time. We will learn to count exact cycles later on in the book)
    con
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000
    
    pub main
    cognew(@toggle3, 0)
    
    dat
              org      0                   'start of the program storage locations
    toggle3   mov      dira,   #%11        'pin now sets lines 0 and 1 as outputs
              mov      outa,   #%01        'sets the two bits   
    :loop
              call     #clkdelay           'call the delay subroutine
              shl      outa,   #%1         'shift left one bit
              call     #clkdelay           'call the delay subroutine
              shr      outa,   #%1         'shift back right one bit 
              jmp      #:loop
           
    clkdelay  mov      time, deltime       'the delay subroutine, load deltime into toime
    take4                                  'imternal to subroutine flag
              sub      time, #1   wz       'sub 1 from time and set flag if 0
      if_nz  jmp       #take4              'if flag not 0 go back to take4
    clkdelay_ret     ret                   'return for delay subroutine
    
    deltime    long    5_000_000           'time of delay
    time       res     1                   'location for time
    
    Program XXX
    Subroutine creation and use for 0.25 second delay.


    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    I'm not sure archaic is a good word in the contexts you use. Simple seems a more fitting term.
    The first 2 examples wont compile of course, so I suppose in that way they are "old and no longer in use."

    The new code in your next example is bad:
    :loop  waitcnt  time,   delay          'the wait instruction
           or      outa,   %01             'sets output 0 on and 1 off
    ...
    

    What's wrong with this? %01 refers to the content of COG address 1 which in the given case will be $a0bfcc?? .... Can't tell extactly what value it will be because pin is not in the second listing and the program will not compile. The program might actually half work if pin was on register address 10.

    Your last example gives a 0.5 second delay. If could be about 0.25s delay if you used "djnz time,#$".

    Other than those problems, I like your progressive examples.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Also, you don't get anywhere with or to switch pins on and off. On yes, off never. I think what you meant to use was mov which would at least match your comments.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Here is my version, using only mov as first stepping stone with mostly indirect numbers.
    CON
            _clkmode = xtal1 + pll16x   'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
    
      
    PUB   main
          cognew(@entry,0)
    
    
    DAT
    entry   mov dira,#%11           'pin p0 and p1 as output
            mov time,#5             'first time we only want to wait 0 clock(+ 5 for the overhead) 
            add time,cnt            'add current counter value to time
    
    loop    waitcnt time, delay     'wait until counter matches time, when done add delay to time
            mov outa,#%01           'set pin p0 high, p1 low
    
            waitcnt time, delay     'wait, time had 15million added to it from above waitcnt opcode  
            mov outa,#%10           'set pin p0 low, p1 high
            jmp #loop               'jmp to loop, don't forget the # sign  
    
    delay long 15_000_000           '15 million clock cycles, underscores is just for easy reading by human eyes.
    time  res 1
    

    2nd updated version, that shows better programming style.
    CON
            _clkmode = xtal1 + pll16x     'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
    
      
    PUB   main
          cognew(@entry,0)
    
    
    DAT
    entry   mov dira,output         'set outputs 
            mov time,#5             'first time we only want to wait 0 clock(+ 5 for the overhead) 
            add time,cnt            'add current counter value to time
    
    loop    waitcnt time, delay     'wait until counter matches time, when done add delay to time.
            or outa, pin1           'set pin1 high
            andn outa,pin2          'set pin2 low
    
            waitcnt time, delay     'wait, time had 15million added to it from above waitcnt opcode.  
            andn outa,pin1          'set pin1 low
            or outa, pin2           'set pin2 high
    
            jmp #loop               'jmp to loop, don't forget the # sign.   
    
    delay   long 15_000_000         '15 million clock cycles 
    pin1    long 1<<0               '1 shifted zero(p0) steps up = 1  (= %00000001)
    pin2    long 1<<1               '1 shifted one(p1) step up  = 2   (= %00000010)
    output  long 1<<0 | 1<<1        '| =or, so ora the pins we want as output 
    
    time  res 1                     
    

    3rd way with xor, and declaring values in CON sections.
    CON
            _clkmode = xtal1 + pll16x     'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
            pin1= 0 'p0 (use a value between 0 and 31)
            pin2= 1 'p1 (though 28-31 is sometimes reserved)      
    
      
    PUB   main
          cognew(@entry,0)
    
    
    DAT
    entry   mov dira,output         'set outputs
            or outa,led1            'set pin1 high
            mov time,#5             'first time we only want to wait 0 clock(+ 5 for the overhead) 
            add time,cnt            'add current counter, don't add code between this and next line
                                    ' without adding at least 4 to the #5 above for each line added.
    :loop   waitcnt time, delay     'wait until counter matches time, when done add delay to time.
            xor outa, output        'bit invert all output pins. 
            jmp #:loop              'jmp to :loop, don't forget the # sign.   
    
    delay   long 15_000_000         '15 million clock cycles 
    led1    long 1<<pin1            '1 shifted steps up
    led2    long 1<<pin2            '1 shifted steps up  
    output  long 1<<pin1 | 1<<pin2  '| =or, so ora the pins we want as output
    
    time  res 1                     'hint: time can be replaced with cnt, yes cnt the shadow register.
    
  • edited July 2011 Posts: 539Vote Up0Vote Down
    @Jazzed
    I compiled and ran all the programs. They all work, though you may well be right about using
    better technique, (which I have not yet developed and welcome help with).
    @Kuroneko
    Good point. I understand what you are saying.
    @ Tony, I'll add your code as another way of doing it. Later during the final edits. Thanks.

    When do I use
    :loop and jmp #l:loop
    and when do I use l
    loop and jmp #loop
    and is there a difference?

    Harprit.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    :loop, with colon you are allowed to reuse that name so you can call them all by the name :loop (with another label name in between)
    instead of having to use loop1, loop2 etc.
    good if you cut and paste code in as they all probably use the name loop somewhere.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Harprit wrote: »
    @Jazzed
    I compiled and ran all the programs. They all work, though you may well be right about using
    better technique, (which I have not yet developed and welcome help with).
    Technique is subjective - compiling is not.

    It's very likely that you had copy/paste errors. The second program as originally posted would never even successfully compile without the pin variable defined. I suggest you be more careful with what you post.

    --Steve
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Question:

    I am writing the code (done) to read two potentiometers from an MCP 3202 chip (all of it in PASM)
    When I get done, the data is in two variables in the Cog that read them (in PASM.)
    How do I relate these two registers to two named values in SPIN so that I can send them
    to the Parallax Serial Terminal to see if what I did was right.

    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Harprit wrote: »
    Question:

    I am writing the code (done) to read two potentiometers from an MCP 3202 chip (all of it in PASM)
    When I get done, the data is in two variables in the Cog that read them (in PASM.)
    How do I relate these two registers to two named values in SPIN so that I can send them
    to the Parallax Serial Terminal to see if what I did was right.

    Harprit

    Add a mailbox with the start address passed to PAR via cognew. Example:
    {{
    ===========================================================
    sample pasm mailbox interface
    ===========================================================
    }}
    con
      _clkmode = xtal1 + pll16x
      _clkfreq = 80_000_000
    
    var
      long mailbox, data1, data2
      long cog
    
    obj ser: "FullDuplexSerial"
    
    {{
    -----------------------------------------------------------
    main demo loop
    -----------------------------------------------------------
    }}
    pub demo
    
    ' start up the serial driver
    '
      ser.start(31,30,0,115200)
    
    ' wait for serial driver to start up ... very imprecise
    '
      waitcnt(clkfreq+cnt)
    
    ' start up adc reader pasm
    '
      start
    
    ' read and display values once per second
    '
      repeat
    
        readAdc                     ' assuming a command is used for the read
    
        ser.hex(data1, 8)           ' show data
        ser.tx(" ")
        ser.hex(data2, 8)
        ser.str(string($d,$a))      ' newline for everyone
    
        waitcnt(clkfreq+cnt)        ' wait a second
    
    {{
    -----------------------------------------------------------
    start the pasm code with mailbox control
    -----------------------------------------------------------
    }}
    pub start
    
    ' start with non-zero in mailbox so we know when cog has started
      mailbox := -1
    
      cog := cognew(@pasm, @mailbox)+1
    
    ' wait for cog to start
      repeat while mailbox
    
    {{
    -----------------------------------------------------------
    cogstop method
    -----------------------------------------------------------
    }}
    pub stop
      if cog > 0
        cogstop(cog~ - 1)
    
    {{
    -----------------------------------------------------------
    mailbox interface code for reading ADC on demand
    -----------------------------------------------------------
    }}
    pub readAdc
    '' optional read command
    '' if not used, remove cmdWait code in the pasm
      mailbox := -1
      repeat while mailbox
    
    {{
    ===========================================================
    pasm for using mailbox interface
    ===========================================================
    }}
    dat  org
    pasm
    cmd           mov       $, par
    cmdp          mov       $, cmd
    d1p           add       cmd, #4
    d2p           mov       d1p, cmd
    d1            add       cmd, #4
    d2            mov       d2p, cmd
    
    zero          long 0 ' 0 is nop and is used for command done
    
    cmdDone ' tell start code the COG is running
                  wrlong    zero, cmdp
    
    cmdWait ' optionallly wait for read command
                  rdlong    cmd, cmdp
            ' TODO add waitcnt here to lower COG power consumption
                  tjz       cmd, #cmdWait
    
            ' read adc data to d1 and d2
            ' TODO call your read subroutine(s) here
    
                  wrlong    d1, d1p
                  wrlong    d2, d2p
            '
            ' end of main loop
            '
                  jmp #cmdDone
    
    {{
    ===========================================================
    end of file
    ===========================================================
    }}
    

    I use short variable names since I find such code easier to read.
    I find comments above statements easier to read, but I also put them in line often.

    Notice that cmdWait is a loop that does nothing until a valid command comes.
    This loop is optional, but with a waitcnt can save power.

    Result below prints the instructions at address d1 and d2.
    Your PASM ADC reader code would save ADC values there.
    c:\Propeller\harprit>bstc -d com6 -p0 -f -Ograux -L c:\bstc\spin mailbox_demo.spin
    Brads Spin Tool Compiler v0.15.4-pre3 - Copyright 2008,2009 All rights reserved
    Compiled for i386 Win32 at 19:57:58 on 2010/01/15
    Loading Object mailbox_demo
    Loading Object FullDuplexSerial
    Program size is 740 longs
    Compiled 230 Lines of Code in 0.01 Seconds
    We found a Propeller Version 1
    Propeller Load took 0.609 Seconds
    
    c:\Propeller\harprit>uterm com6 115200
    80FC0004 A0BC0600
    80FC0004 A0BC0600
    80FC0004 A0BC0600
    80FC0004 A0BC0600
    80FC0004 A0BC0600
    &#8592;
    All done.
    
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Steve:

    Thanks for taking a such large chunk of your precious time to write the code you posted above
    I will have questions as I try to understand it all but right now I have work to do just understanding it.
    Thanks again

    Harprit.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Harprit wrote: »
    Steve:

    Thanks for taking a such large chunk of your precious time to write the code you posted

    No big deal. I do it all the time, so it's relatively quick and easy.
    The hard part is making sure it compiles.
    The harder part is making sure it works.
    The hardest part is communicating what it's all supposed to do :)

    On retrospect, I realized the first lines of pasm were not obvious. Here are some comments.
    dat org
    pasm
    cmd           mov       $, par  ' read par value to cmd with "$" ($ means the address of this line).
    cmdp          mov       $, cmd ' cmd is used as a temp variable, set cmdp to par address via cmd
    d1p           add       cmd, #4 ' add 4 to address so that we can find data 1's pointer "d1p"
    d2p           mov       d1p, cmd ' assign address to data 1 pointer
    d1            add       cmd, #4 ' add 4 to address so that we can find data 2's pointer "d2p" 
    d2            mov       d2p, cmd ' assign address to data 2 pointer - d1 and d2 get overwritten
    

    Cheers.
  • edited July 2011 Posts: 539Vote Up0Vote Down
    Question for experts:

    I've been banging my head against the wall all afternoon with the above code and now I have a question
    I have not tried this yet but...
    Why is it not possible for me to write a 32 bit value to the main memory with WRLONG in the cog written in PASM and then
    read that same memory location with WORD in another cog written in SPIN

    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    now to find out this I would store two different values that are easy to discover as hexnumbers and then using PASD to find the locations in the HUB-RAM
    maybe it has something to do with that SPIN-variables become reordered in HUB-RAM longs words bytes

    Please add your code to a posting. With your code it will be much easier to explain what happens

    best regards

    Stefan
    [x] <== SLAM in nail here to hook up the new screen! :lol:
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Harprit wrote: »
    I've been banging my head against the wall all afternoon with the above code and now I have a question
    Maybe you should limit your wall banger time to 15 minutes or less before asking for help.

    I suspect that you need to do lots more reading.

    All you have to do is use the same address for your PASM write as for your SPIN read. it doesn't matter how you get your address - you may end up corrupting something though if it's not allocated as a variable.

    Yes, by all means paste your code here, and someone can tell you what the problem is.

    I've seen using a debugger mentioned twice now. Maybe you really should follow that advice.

    I use this http://forums.parallax.com/showthread.php?115068-BMA-Multi-COG-PASM-Debugger-V1.9-Now-Available&p=829927&viewfull=1#post829927. I started using PASD long ago, but quickly found it "limiting."

    I use my debugger any time i don't understand why something is not working, and it's usually something really stupid that's causing the problem.

    A debugger can present several new challenges though. Sometimes more real-time tools are necessary.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    ... it might be as simple as a long not fitting into a word ...

    Following up on [post=1020338]post #40[/post] you really should get into the habit of matching your comments with the code. Finding blindingly obvious contradictions isn't going to help the beginner and they get distracted from the actual lesson or - worse - give up.
  • edited July 2011 Posts: 0Vote Up0Vote Down
    @jazzed:
    tried again your debugger. You wrote PASD is "limited". Could you please explain what are the advantages of BMA-Debugger over PASD?
    looking up the memory through dumping and then have the code out of sight looks uncomfortable to me. So from testing it I did not see what the advantage is

    best regards

    Stefan
    [x] <== SLAM in nail here to hook up the new screen! :lol:
  • edited July 2011 Posts: 539Vote Up0Vote Down
    I had hoped that some beginner would participate but so far no one has.
    Beginners would lend a different perspective.
    My postings reflect what I am up to at my computer.
    This is at least 50 times more difficult than writing in SPIN. I have to feel my way through the haze.
    Comments received have been very helpful special the sample programs because I need to see real code that I can understand.
    Later today I will post my efforts to write a word in PASM and read it in SPIN. So far I am having difficulty addressing the same memory location in hub from both cogs.

    See following (kuroneko's) post, so no need to me to post by me.

    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Here would be one example for sharing a memory location (demoboard):
    PUB null | shared
    
      cognew(@generate, @shared)                    ' start incrementer
    
      dira[16..23]~~                                ' all LEDs are outputs
      repeat                                        ' endless loop
        outa[16..23] := shared.byte[2]              ' display byte 2 only
    
    DAT             org     0
    
    generate        add     temp, #1                ' simply increment our value
                    wrlong  temp, par               ' share with SPIN cog
                    jmp     #generate               ' endless
    
    temp            res     1                       ' temporary (yes, blindingly obvious)
    
                    fit
                    
    DAT
    
    The important thing here is that par is only 14bit in size (16bit in fact with bits 0 and 1 equal 0, i.e. a 4n aligned address). HTH
  • edited July 2011 Posts: 0Vote Up0Vote Down
    StefanL38 wrote: »
    You wrote PASD is "limited". Could you please explain what are the advantages of BMA-Debugger over PASD?
    Everyone has their own tastes.
    What is simple to some may be overwhelming for others.
    What is limiting to some may be overwhelming for others.
    What is less limiting to some may be overwhelming for others.

    Things with less limits tend to be more complicated in some ways:
    Think MAC -vs- UNIX ... up until OS-X that is :)
    BMA/PASD Comparisons
    
    BMA                                     PASD
    Step animation record                   No step animation record
    Multi-COG debugger                      Single COG debugger only
    Can use any complier                    Must use Propeller Tool
    Command line tool + terminal program    Windows program
    Needs long 0 [8] at addr 0 for stub     User adds 12 instructions at addr 0
    Requires using listings for symbols     Has symbol address/data in windows
    
    BMA is best used in conjunction with BSTC / Homespun listings.
    Listings show the best picture of what is in the chip at startup.
    Listings show all object DAT addresses and data.
    Listings show all spin code.
    
    PASD scans the Propeller Tool and can cause lock up if compile fails.
    
    Both provide COG + HUB memory view/edit
    BMA also has print special register command.
    BMA is an on chip debugger and can be used with SpinSim.
    PASD hub footprint is smaller than BMA.
    

    The step animation record below is of great value.
    It steps through kuroneko's example showing all transactions.

    Displayed are the COG address, any special effects (none),
    instruction name/code, destination and source information.
    c:\bstc\spin>bstc -d com6 -p0 -f -Ograux -L c:\bstc\spin pasmled.spin
    Brads Spin Tool Compiler v0.15.4-pre3 - Copyright 2008,2009 All rights reserved
    Compiled for i386 Win32 at 19:57:58 on 2010/01/15
    Loading Object pasmled
    Loading Object FullDuplexSingleton
    Loading Object BMAUtility
    Loading Object BMAopcodes
    Loading Object BMADebugger
    Loading Object BMAPASMstub
    Program size is 8748 longs
    1 Constants folded
    Compiled 1190 Lines of Code in 0.048 Seconds
    We found a Propeller Version 1
    Propeller Load took 1.432 Seconds
    
    c:\bstc\spin>uterm com6 115200
    
    
    Starting BMA Debugger ...
    
    BMA Debugger Started.
    T0.PC 008 Ok> a
    T0.PC 008 .      : add     80fc1601     D:00b  381f3801 S#001           D=00b  381f3802
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3802 S:PAR  0000258c D=00b  381f3802
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3802 S#001           D=00b  381f3803
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3803 S:PAR  0000258c D=00b  381f3803
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3803 S#001           D=00b  381f3804
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3804 S:PAR  0000258c D=00b  381f3804
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3804 S#001           D=00b  381f3805
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3805 S:PAR  0000258c D=00b  381f3805
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3805 S#001           D=00b  381f3806
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3806 S:PAR  0000258c D=00b  381f3806
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3806 S#001           D=00b  381f3807
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3807 S:PAR  0000258c D=00b  381f3807
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3807 S#001           D=00b  381f3808
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3808 S:PAR  0000258c D=00b  381f3808
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3808 S#001           D=00b  381f3809
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f3809 S:PAR  0000258c D=00b  381f3809
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f3809 S#001           D=00b  381f380a
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f380a S:PAR  0000258c D=00b  381f380a
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f380a S#001           D=00b  381f380b
    T0.PC 009 .      : wrlong  083c17f0   N D:00b  381f380b S:PAR  0000258c D=00b  381f380b
    T0.PC 00a .      : jmp     5c7c0008   N D:000  083c01f3 S#008           D=000  083c01f3
    T0.PC 008 .      : add     80fc1601     D:00b  381f380b S#001           D=00b  381f380c
    T0.PC 009 Ok>
    

    Here is kuroneko's LED blinker with changes to support the BMA debugger.
    CON
        _clkmode = xtal1 + pll16x
        _clkfreq = 96_000_000
    
    OBJ
      ser : "FullDuplexSingleton"
      deb : "BMAUtility"
    
    PUB null | shared
    
      ser.start(31,30,0,115200)
      waitcnt(clkfreq+cnt)
    
      deb.debug(@generate, @shared)
      'cognew(@generate, @shared)                    ' start incrementer
    
      dira[16..23]~~                                ' all LEDs are outputs
      repeat                                        ' endless loop
        outa[16..23] := shared.byte[2]              ' display byte 2 only
    
    DAT             org     0
    generate
    long 0 [8]      ' required for debugger
    
    :loop           add     temp, #1                ' simply increment our value
                    wrlong  temp, par               ' share with SPIN cog
                    jmp     #:loop                  ' endless
    
    temp            res     1                       ' temporary (yes, blindingly obvious)
    
                    fit
    
  • edited July 2011 Posts: 539Vote Up0Vote Down
    @ kuroneko

    Thanks.
    I got out my demo board and ran your program.
    Then..
    I eliminated the last two lines of your program as I could not understand what they did.
    I still works but I wondered of I had missed something. Did I do it right?
    Can one say that the RES area has to list all variables that will be used in the program and
    that all constants have to be listed as " value long 2000" which means that these are
    the equivalent of the VAR and CON areas of a SPIN program?

    I really appreciate your crisp input.

    @stephan

    Though I intend to learn to use a debugger later on, I am not sure that they are useful beginner's tools.
    Too long a learning curve to allow them to use them effectively in the beginning stages.
    Besides they want to learn PASM not debuggers. I think that comes later.
    I may change my mind and (at this stage) I may well be wrong.
    I say this because with all its mistakes in it, beginners still like my very simple SPIN book very much.
    The criticisms are from people who already know SPIN rather well, but then the book is not for them!
    I would like the PASM book to be similarly received.

    Harprit
  • edited July 2011 Posts: 0Vote Up0Vote Down
    Anyone with enough desire will learn anything by any means including buying a book written by someone who knows little about the subject. Published books "project" a certain amount of credibility. People who know better and have several worthless beginners books will always be more selective. Fortunately for publishers, there always will be a near infinite flow of naive beginners.
  • edited July 2011 Posts: 539Vote Up0Vote Down
    @ Steve

    I hate saying this.
    I don't think that was helpful, polite or necessary.
    I know that you are very knowledgeable about the subject and respect you for that,
    however such comments are not furthering the discussion.
    I sincerely need and ask for help. Above comments are not helping or encouraging.
    Would you please, if I may, seriously consider opting out of this discussion.
    If not, I will ignore and not respond to anything nonconstructive that you have to say.

    Harprit
Sign In or Register to comment.