Shop OBEX P1 Docs P2 Docs Learn Events
Propeller Assembly for beginners - Page 23 — Parallax Forums

Propeller Assembly for beginners

1202123252629

Comments

  • HarpritHarprit Posts: 539
    edited 2013-01-22 15:00
    ph

    Tell me about it!
    And I do agree with what you have said.

    You are more right than you can imagine. I have been sincerely beating my head against this for a year and a half. Essentially more than full time. It is really very complicated and to do it right, this Propeller 102 effort (101 was my SPIN book) needs to be followed by Propeller 103 on slightly more advanced stuff like you are suggesting. Propeller 104 for advanced projects and 495 for what the experts need to know. I do not know that I am the guy for that.

    I'll see what I can add but I am not hopeful to do it justice.

    Thanks

    H
  • potatoheadpotatohead Posts: 10,261
    edited 2013-01-22 15:02
    Given that, I highly recommend you perform an analysis of the COGS you cite in your text, decide how to start them consistently and at the least explain that.
  • HarpritHarprit Posts: 539
    edited 2013-01-26 12:39
    Here is a short program I am having problems with
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
       vars=20
    OBJ 
      fds : "FullDuplexSerial"         'for communications with PST
    
    VAR  
      long stack2[25]                   'space for pulser cog
      long clk_Div,value[vars]
      byte sub_scr
       
    PUB Main|x                        'x is a local variable here
    fds.start(31,30,0,115200)         'start console at 115200 for debug output 
    Cognew(@Read_Sig,      @value)
    'dira[0..1]~~                      'set lines to outputs          
    fds.tx(16)                    'home to 0,0
      repeat
        fds.tx(1)                                         
        fds.str(string("HUB memory display"))     'print to display 
        fds.tx($d)                   'new line
        fds.tx($d)
        repeat sub_scr from 0 to 11
          if sub_scr<10
            fds.str(string(" "))
          fds.dec(sub_scr)
          fds.str(string("   "))                    
          fds.dec(||value[sub_scr])
          fds.str(string("           "))    'print spaces to erase old data overflow
          fds.tx($d)                    'new line  
      
        waitcnt(clkfreq/60+cnt) 'flicker free wait
        x:=x+1          'increment counter. This routine clears up screen
        if x>100        'decision point     by erasing extraneous lines of bottom
          fds.tx(16)    'clear screen       of PST display every 100 loops
          x:=0          'reset counter     
    
    DAT               Org       0           '
    Read_Sig  mov     nmbr,     #0          'initialize nmbr
              mov     mem,      par         'read par into mem
              mov     mem1,     mem         'make mem1= to mem
              add     mem1,     #4          'add 4 to mem1 for next loc
                                            '
    do_again  mov     temp,     cnt         'read counter to temp         
              wrlong  temp,     mem         'store in first location  
              add     nmbr,     #1          'increment number
              add     mem,      #4          'add 4 to mem 
                                            '
              mov     varbl,    nmbr        ' remember nmbr
              sub     varbl,     #5   wz    ' has it reached 5
        if_nz jmp     #do_again             ' if not do again
                                            ' reaches 5 at this point
              rdlong  temp,    mem          ' read temp from 1st location
              wrlong  temp,    mem1         ' write it to second location
    park      jmp     #park                 'go into loop
    
    
    mem       res     1 
    mem1       res    1   
    temp      res     1    
    Nmbr      res     1    
    varbl      res    1 
    

    You can run it, it needs no connections to anything. See results on PST.
    The program creates two Hub location addresses relative to PAR, mem and mem1
    It then reads the system counter 5 times and stores the results in Hub memory. first 5 locations.
    It then read location mem and writes it to location mem1
    However It stores a 0 in that location.
    Creating mem1 seems to wipe out the contents at mem
    What is wrong.

    H
  • John AbshierJohn Abshier Posts: 1,116
    edited 2013-01-26 14:39
    rdlong temp, mem ' read temp from 1st location
    mem is no longer 1st location because you have been adding to in in the do_again loop

    John Abshier
  • HarpritHarprit Posts: 539
    edited 2013-01-26 15:54
    Thanks John
    H
  • frank freedmanfrank freedman Posts: 1,983
    edited 2013-01-27 01:11
    Or you could try this:
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
       vars=8
    OBJ 
      fds : "FullDuplexSerial"         'for communications with PST
    
    
    VAR  
      long stack2[25]                   'space for pulser cog
      long counter,value[vars]
      byte sub_scr
       
    PUB Main '|x                        'x is a local variable here
    fds.start(31,30,0,57600)         'start console at 115200 for debug output
    counter := vars
    Cognew(@Read_Sig, @counter)           ' start a cog sending the location of data array..
             
    fds.tx(16)                    'home to 0,0
        fds.tx(1)                                         
        fds.str(string("HUB memory display"))     'print to display 
        fds.tx($d)                   'new line
        fds.tx($d)
        fds.str(string("samples "))                    
        fds.dec(||vars)
        fds.tx($d)                    'new line  
        fds.str(string("base address "))                    
        fds.dec(||value[0])
        fds.tx($d)                    'new line  
        repeat sub_scr from 1 to (vars)
          fds.dec(sub_scr)
          fds.str(string("   "))                    
          fds.dec(||value[sub_scr])
           fds.tx($d)                    'new line  
         
    
    
    DAT               Org       0        
    Read_Sig  mov     mem,   par        ' save base address. 
              rdlong  varbl, mem        ' get the sample count from spin parameters
              add     mem,   #4         ' point to start of hub storage + 1 long or we step on the count in hub memory
              mov     temp,  par        ' get base addx into temp; store this second location count is in first location      
              wrlong  temp,  mem        ' save base in hub for later readback w/ spin code..
              add     mem,   #4         ' now we point to the first count value  location
    do_again  mov     temp,  cnt        ' get count, 
              wrlong  temp,  mem        ' store in value to hub.   
              add     mem,   #4         ' calc next location to store a long 
              djnz    varbl, #do_again  ' this falls through at 0,
              
    park      jmp     #park             ' loop here forever
    
    
    varbl     long 0
    mem       res  1   
    temp      res  1
    
    
    fit $1EF
    
    

    Output
    HUB memory display


    samples 8
    base address 1048
    1 1003196230
    2 1003196250
    3 1003196282
    4 1003196314
    5 1003196346
    6 1003196378
    7 1003196410
    8 1003196424
  • HarpritHarprit Posts: 539
    edited 2013-02-03 08:24
    I just posted some tachometer code in PASM to the forum
    It will be of interest to beginners
    I did not re-post here to keep down the clutter.

    Please post comments that might need inclusion re: book.

    The book is about done and ready for printers.
    I give it two weeks for "in their hands"

    H
  • HarpritHarprit Posts: 539
    edited 2013-02-08 06:13
    I am debugging a project in the book
    It creates a PASM interface for a standard Hitachi controlled 2 x 16 display.
    I have an equivalent routine in SPIN that runs fine.

    When I translate into PASM I write "A...H" to the first line.
    Everything works but the last char H" does not print.
    As a matter of fact the device is printing the previous character ever time I send out a new character.
    The last character is held hostage.
    I think it is some sort of timing problem but I cant figure out what, or which.

    Here is the code. testdata packs "ABCD" in the long
    {{-------------------------------------------------------------------------------
    BookLCD_2x16.SPIN
    Function of program
    Implements the use of a 2 line by 16 character
    in PASM. Data is written to the LCD in PASM or through the HUB memory.
    See book for details and operation scheme
    
    Connections are as follows
    Prop    LCD
            16  Ground                   LED
            15  5 volts through 220 ohms  LED
            
    0       14   data buss
    1       13      "
    2       12      "
    3       11      "
    4       10      "
    5       9       "
    6       8       "
    7       7    data buss
                                        
    20      6    ENable
    21      5    Read Write
    22      4    Reg Select  
            3    Ground
            2    5 volt     Power Logic
            1    Ground
    
    Program         BookLCD_2x16.SPIN                       
    Book            PASM for beginners, Propeller 101
    Section         Projects
    Programmer      Harprit Sandhu   
    Date            Feb 10 2013
    
    Revisions:      Report errors to harprit.sandhu@gmail.com
    
    
    
    
    
    -------------------------------------------------------------------------------}}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      Vars =32     'hub variables to be displayed
      
    VAR
      long  stack1[35]
      long  P_Val[vars]
      byte  subscr
      
    OBJ
      fds : "FullDuplexSerial"
      r4p : "Read4Pots"
    
    PUB Go|x           
    r4p.Read4Pots(@P_Val)                   
    Cognew(@display,  @P_val)                                             
    fds.start(31,30,0,115200)       'start PST console at 115200 for output  
    waitcnt(clkfreq/60+cnt)    
    'Cognew(@Write_LCD,  @P_val)
    waitcnt(clkfreq/60+cnt)           
    repeat
    '{{                                                                    
       fds.tx(1)                    'home                                  
       fds.str(string("Displaying Hub variables")) 'heading                                                                                              
       fds.str(string("  "))        'two spaces to erase old data overflow  
       fds.tx($d)                   'new line                        
       fds.tx($d)                   'new line 
       '    fds.str(string("7654321076543210")) 
       '    fds.tx($d)               'add line                   'reset subscript
       repeat subscr from 0 to vars-1                 'loop to display all vars  
         if subscr==2
           fds.tx($d)                                                           
         fds.bin(P_Val[subscr], 32) 'print to the PST in binary                                                                                                               
         fds.str(string("   "))     'two spaces to erase old data overflow 
         if subscr<10
           fds.str(string(" "))                                                                                                      
         fds.dec(subscr)            'print value as decimal value                                                                                                                
         fds.str(string("   "))     'three spaces to erase old data overflow
         fds.dec(P_Val[subscr]) 'print to the PST in binary                                                                                                                  
         fds.tx($d)
                                                         
       waitcnt(clkfreq/60+cnt)      'wait 1/60 for everything to stabilize. 
       x:=x+1             'increment counter. (This routine clears up the screen    )
       if x>10           'decision point     (by erasing extraneous lines of       )
         fds.tx(16)       'clear screen       (bottom of PST display every 10 loops)
         x:=0             'reset counter      (Needed only once in most cases.      )
    '}}
         
    DAT       org     0         
    display   mov     mem,      par        'Read Par into mem           
              mov     dira,     set_dir    'Set directions                                         
              mov     ddata,    half_sec   'load half second
              call    #wait                'wait half second
              call    #Init_LCD            'call initialize routine   
              mov     ddata, half_sec      'load half sec
              call    #wait                'wait
    display3 '=======================================
              rdlong  data, mem             'read forst Hub mem location
              shr     data, #5              'shift right 5 to reduce sensitivity
              call    #send_char            'lsend out what was read as ASCII code
              mov     data,    #66          'load B
              call    #send_char             'send out B
              mov     data,    #(00_0011) 'load C
              call    #send_char            'send out 
              mov     data,    #68          'load D
              call    #send_char            'send out 
              mov     data,    #69          'load E
              call    #send_char            'send out 
              mov     data,    #70          'load F
              call    #send_char            'send out 
              mov     data,    #71          'load G
              call    #send_char            'send out 
              mov     data,    #72          'load H
              call    #send_char            'send out 
              jmp     #display3             'loop back
    'stop jmp #stop
    'subroutines=====================================================================
    Init_LCD      
              andn    outa,     setRw       'RW set low 
              andn    outa,     setRs       'RS set low
              andn    outa,     setEN       'set EN hi
              mov     data,    #(11_0000) 'load instruction
              call    #send_Instr           'send out instruction
              mov     data,   delay1        'load delay
              call    #wait                 'wait             
              mov     data,    #(11_0000)'load instruction 
              call    #send_Instr           'send out instruction
              mov     data,   delay2        'load delay
              call    #wait                 'wait            
              mov     data,    #(11_0000)'load instruction 
              call    #send_Instr           'send out instruction
              mov     data,   delay3        'load delay
              call    #wait                 'wait
              '======================       '                           
              mov     data,    #(11_1000)  'clears blocks
              call    #send_Instr           'load instruction
              call    #wait_2ms             'wait              
              mov     data,    #(00_1111) 'cursor etc
              call    #send_Instr           'load instruction
              call    #wait_2ms             'wait                     
              mov     data,    #(00_0001) 'clear
              call    #send_Instr           'load instruction
              call    #wait_2ms             'wait                      
              mov     data,    #(00_0010) 'home
              call    #send_Instr           'load instruction
              call    #wait_2ms             'wait 
    Init_LCD_ret          ret               'Return
                                            '
    '============================           '
    wait      mov     temp,     ddata       'load passed data
    :loop     djnz    temp,     #:loop      'wait loop
    wait_ret  ret                           'return
    '===========================            '
                                            '
    wait_2ms  mov     temp,     d2ms        'load 2 ms
    :loop     djnz    temp,     #:loop      'wait loop
    wait_2ms_ret      ret                   'return
    '========================               '
    Send_Instr call   #busy                 'Check busy flag
              andn    outa,     setRw       'RW set low 
              andn    outa,     setRs       'RS set low
              or      outa,     setEN       'set EN hi
              call    #wait_2ms             'wait 2 ms
              mov     outa,     data        'load outa 
              call    #wait_2ms             'wait 2 ms 
              andn    outa,     setEN       'toggle EN lo 
              call    #wait_2ms             'wait 2 ms 
    Send_Instr_ret    ret                   'retuirn
    '=========================================================  
    Send_Char call    #busy                 '
              andn    outa,     setRw       'RW set low
              or      outa,     setRs       'RS set hi
              or      outa,     setEN       'set EN hi
              call    #wait_2ms             'wait 2 ms 
              mov     outa,     data        'load outa 
              call    #wait_2ms             'wait 2 ms 
              andn    outa,     setEN       'toggle EN lo
              call    #wait_2ms             'wait 2 ms 
    Send_Char_ret     ret                   'reutrn
    '========================               '
    Busy                                    '
              mov     dira,     Set_Inp     'change to input byte
              or      outa,     setRw       'RW set hi
              andn    outa,     setRs       'RS set lo    
                                            '                 
    :loop     or      outa,     setEN       'set EN hi
              mov     temp,     ina         'read input lines
              andn    outa,     setEN       'set EN hi 
              andn    temp,     mask7 wz    'look at busy bit
       if_nz  jmp     #:loop                'loop back if not a 0
              mov     dira,     Set_Dir     'set back to output lines
              call    #wait_2ms             'wait 2 ms
    Busy_ret          ret                   ' return
    
    'constants=====================================================================
    half_sec  long  2_000_000   '0.5 sec         approx values            
    delay1    long      5_000   '4.1 milli       largest the system
    delay2    long        300   '100 micro       will still work
    delay3    long      3_000   '1 milli         with.
    d2ms      long        400   '2 ms
    set_Dir   long  000000_11111111_00000000_11111111
    set_Inp   long  000000_00000000_00000000_00000000                                                                       
    setEN     long  000000_00010000_00000000_00000000                                                                       
    setRW     long  000000_00100000_00000000_00000000                                                                      
    setRS     long  000000_01000000_00000000_00000000
    mask7     long  111111_11111111_11111111_01111111   'mask for pin 7
    
    'variables====================================================================
    Mem_Loc   res     1
    mem_Val   res     1
    sent      res     1       
    cmd       res     1       
    temp      res     1
    pip       res     1
    temp2     res     1  
    temp3     res     1  
    temp4     res     1
    mem       res     1
    mem1      res     1
    bits      res     1       
    data      res     1
    ddata     res     1
    

    H
  • ChrisGaddChrisGadd Posts: 310
    edited 2013-02-08 14:09
    The problem whereby the routine is holding the last character hostage is due to raising the enable line high before setting the data lines. Setting the data lines first, and then toggling the enable line high and low causes the display to show the expected character, but it also reveals the bug that I was expecting to see from a read through; I am amazed that it managed to get up to G as written. With the enable line toggling after the data lines are set, the display only shows the "A" and "B", and then the cursor jumps. To set the data lines, you're copying the contents of data into outa, which is overwriting the R/W and RS lines. It's just dumb luck that because of the way test_data is packed with four ASCII bytes that the RS bit remains set the first two times through. Following the third shift, however, RS is clear.

    I sure hope the book is better looking than this.
  • HarpritHarprit Posts: 539
    edited 2013-02-09 09:19
    Thank you Chris.

    I hope you will not be disappointed.
    I am giving it my best shot but my lack of sophistication will no doubt show through.

    H
  • HarpritHarprit Posts: 539
    edited 2013-02-11 12:05
    I just read through the book and made a list of all the components needed to do the experiments.
    Here it is as promised.
    [COLOR=#000000][FONT=Arial, sans-serif][SIZE=5]Parts and equipment needs[/SIZE][/FONT][/COLOR]
     
    
     [COLOR=#000000][FONT=Arial, sans-serif]The following parts will allow you to do all the experiments in the book.[/FONT][/COLOR]
     
    
     [COLOR=#000000][FONT=Arial, sans-serif]PDB from Parallax (certain unlisted parts are on the PDB)[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]4 potentiometers 5K to 10k[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]MCP 3208 8 line A to D chip[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]7404 buffer[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]LM34 Temp reading chip[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]2 x 16 LCD display with Hitachi controller[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Memsic 2125 tilt indicator gravity chip[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Resistors  (10 each should be in every supplies drawers)[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	220 ohm[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	470 ohm[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	10K[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	1 meg[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Small transistor for speaker[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Small speaker[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Seven segment display[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Servo, R/C hobby (2 needed)[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Small motor 12 VDC (Opt)[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Motor amplifier (Opt)[/FONT][/COLOR]
      [COLOR=#000000][FONT=Arial, sans-serif]Set of breadboard jumpers with steel tips (highly recommended because hook up wire tends to break in the breadboards after many uses and is then very hard to remove)[/FONT][/COLOR]
     
    
     [COLOR=#000000][FONT=Arial, sans-serif][B]Tools:-[/B][/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Minimal Oscilloscope[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Inexpensive VOM[/FONT][/COLOR]
     
    
     [COLOR=#000000][FONT=Arial, sans-serif]Tool box scraps[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]Sources of parts.[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	Jameco[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	All electronics[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	Mouser[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	Suppliers on internet, eBay.[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	Parallax Inc[/FONT][/COLOR]
     [COLOR=#000000][FONT=Arial, sans-serif]	encodergeek.com[/FONT][/COLOR]
     
    
     [COLOR=#000000][FONT=Arial, sans-serif]Please report omissions to me at [/FONT][/COLOR] 
     [COLOR=#000000][FONT=Arial, sans-serif][B]harprit.sandhu@gmail.com[/B][/FONT][/COLOR]
    

    There might be a minor change or two to it but I think this is it.

    Harprit
  • HarpritHarprit Posts: 539
    edited 2013-02-18 08:11
    I have a question for the experts
    I have an object that read 4 pots and puts the values in the first 4 locations in hub ...P_Val

    When I access the cog with
    VAR
       no mention of P_Val[ ] under  VAR declarations
       long number
    
    OBJ                                                                    
      r4p : "read4pots"             'refers to the pots object
    .....
    .....
    .....
    r4p.Read4Pots(@P_Val)     'starts the method in object above and passes P_Val to it.
    ....
    PUB .......
    number:=P_Val[2]
    ...
    

    I find that in my program I do not have to allow space for P_Val as an array under VAR in my program
    and I can still use P_Val[0], P_Val[1], P_Val[2], P_Val[3] in my program and methods within.
    Compiler does not flag it
    Everything works fine


    Is this the OK and proper use of the code
    Is there something else that needs to be done to be right

    H
  • JonnyMacJonnyMac Posts: 9,159
    edited 2013-02-18 08:30
    r4p.Read4Pots(@P_Val) 'starts the method in object above and passes P_Val to it.

    No... this actually passes the hub address (@) of P_Val, which should be the first of a group of four variables to hold the pot values. This could be an array of four variables, or it could be the first in a list of the same type. The object only needs the base address of the group to write to them all.

    I have written a similar object for the MCP3208 which auto-scans the inputs and populates a designated set of variables. In my program I have something like this:
    var
      long  xaxis
      long  yaxis
      long  zaxis
      long  speed
      long  ramp
    


    In my object's start() method I specify the SPI pins, the number of channels used (5 for the above group), and the hub address of the output variables (@xaxis).
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-02-18 10:42
    Of course you need to declare P_VAL somewhere! Either in VAR or in DAT section. Otherwise the compiler does not know what to do with the label P_VAL in the code and give you an error-message. AND of couse P_VAL needs to be declared in a way that you have reserved enough RAM, as you otherwise overwrite parts of the RAM used otherwise.

    But yes, the compiler does not complain if you use a normal variable as an array. Maybe because in a DAT-section you don't have an array declaration but you definitely want to use labels like an array. So it was easier to allow the compiler to treat VAR variables in the same way.

    Nevertheless you as a programmer have to be aware of the size of an array or label used in the array-style, as otherwise real strange things could happen.

    Examples:
    VAR
      long P_VAL
      long X_VAL
    ..
      P_VAL[1]:=0
    
    This would overwrite X_VAL
    DAT
      P_VAL long 1,2,3,4
    
    This is propably why P_VAL can be used as an array even if it is not declared as such.
  • HarpritHarprit Posts: 539
    edited 2013-02-18 11:22
    Well, these are things that I am coming across as I wrap things up and I want to
    clear up as much of it as I can.

    Thanks to all for the tremendous help you all gave me in the last year and a half.

    I hope to have the index done by the end of Feb

    H
  • rwgast_logicdesignrwgast_logicdesign Posts: 1,464
    edited 2013-02-20 12:51
    Harpit, I have seen some fairly negative comments about your SPIN book, and in this thread. Despite all that your spin book has fairly good amazon reviews. I went ahead and ordered it. Im really looking forward to reading it. While the PE-Kit is a great resource, your book has some stuff in it im really looking forward to, i.e. motor control with encoders, and im really hoping you show the user to write an hd47780 driver, not just use an object.

    Anyways my point is I have Hi Hopes for this PASM book. I know it wont turn me in to a Chip, Phil or Jazzed, but im hoping it will be a good starting point. While both PotatoHead and Desilva both have excellent documents out there. There is a pretty big gap to fill between them. I learned PC assembly from this book http://www.amazon.com/Assembly-Language-Step---Step-Programming/dp/0470497025/ref=sr_1_6?s=books&ie=UTF8&qid=1361393192&sr=1-6&keywords=assembly+language it takes an awesome approach to teaching newbs about ASM, using the first half of the book to go over binary/hex math, and how PC architecture works. This is really what assembly is about, anyone can look at a table of instructions, but having an entament knowledge of the machines architecture is what its all about, thats the only way to figure out how to use those instructions properly.
  • HarpritHarprit Posts: 539
    edited 2013-02-20 15:15
    rw:

    Thanks for taking the time to post.

    I look forward to your reaction to my SPIN book. One of the reviewers liked it enough to wear the binding out. I hope it will help you understand the control of servo motors with encoders. I still provide hardware to support the book if you cant find it elsewhere. I don't know of any other author that does this. Both my books, on running motors and making instruments, along with their electronic copies, 4 of them together have been in the top 50 PIC books for three years now!! If you have a heavy interest in running motors you might want to take a look at the motors book.

    As for some "fairly negative reviews" I can only say that these books are not for experts, never were, never will be. There is a need for another book that should come after my two books (Propeller 101 SPIN, and Propeller 102 PASM). I might do one but right now I am saturated and bushed and getting beaten on does not help. What you are really asking for, in my mind, would go in Propeller 495, for graduate students. Parsing, compiler design, arrays, look up tables, hairier stuff like that. However do me a favor and send me a table of contents that you think should be in Propeller 103. Others of course and invited to do so also. Lets see what we come up with. Could be very interesting.

    However go to Amazon and read the reviews. The books are all well liked and are good sellers. My book on Robotics described the construction of a walking robot (my avatar on this forum) in 1996. 17 years ago!! It was the first weight shifting robot described and all the walking robots of today are based on my book yet only one supplier gives me the credit for figuring it out an telling.

    Thanks again
    H
  • HarpritHarprit Posts: 539
    edited 2013-02-21 06:32
    On the bottom half of page 102 of Prop Manual Ver 1.1 is the instruction example

    rdlong delay, #0 'get clock frequency

    How do I know that this gets the clock frequency.
    And why and how is/was it at location #0
    I see no reference to this anywhere in the manual.

    Will some one knowledgeable please expand on this.

    H
  • HarpritHarprit Posts: 539
    edited 2013-02-21 06:38
    Consider this snipped of code.
    Beats
    P_Var  long  400,555,6
    mov mem, par
    mov mem1, mem
    add mem1, #8
    wrlong P_Var, mem
    wrlong  P_Var, mem1
    here jmp #here
    


    Running this stores 400 at the first and 3rd Par referenced locations
    How do I access the constants 555 and 6 that were specified
    above from within a PASM program.

    H
  • Heater.Heater. Posts: 21,230
    edited 2013-02-21 06:58
    For sure that clock frequency thing is in the manual. It's in Chapter 1 "Introducing the Propeller Chip" in a section called "Main RAM".
  • Heater.Heater. Posts: 21,230
    edited 2013-02-21 07:17
    You could make life easy for yourself by naming all your constants:

    const1 long 400
    const2 long 55
    const3 long 6

    and using those meaningful names in your program.

    Of course for numbers of 9 bits or less just define constants in a CON section and use the hash:
    CON
    const1 = 99
    
    DAT
    ..
    mov a, #const1
    ...
    a long 0
    

    If you really have an array of unnamed constants, a look up table, you will need to use self-modifying code to do it. That is to say use movs and movd to modify your instructions to address the correct location in the table prior to execution. See PASM reference manual.

    I suggest that in general you do not declare your variable or constant longs prior to you executable instructions. Put them at the end.
    Don't forget your ORG and FIT statements.
  • User NameUser Name Posts: 1,451
    edited 2013-02-21 09:33
    Harprit wrote: »
    What you are really asking for, in my mind, would go in Propeller 495, for graduate students. Parsing, compiler design, arrays, look up tables, hairier stuff like that.

    Compiler design might be Propeller 495, but indexing a table is Assembly 101, no matter what processor we're talking about. In fact I'd put it before spinning a motor or writing to a display.

    Admittedly, the Prop does indexing differently than most chips. But it's still a basic operation that needs to be mastered right out of the gate.
  • Heater.Heater. Posts: 21,230
    edited 2013-02-21 10:09
    Somebody,
    Parsing, compiler design, arrays, look up tables,
    You cannot put all these in the same catagory.

    PASM 101 should at least include arrays and look up tables. In HUB and in COG memory. It's basic memory indexing stuff. It may be a bit less obvious on the Prop due to it's lack of support in the instruction set but it is there with self-modifying code.

    Parsers and compilers are an order of magnitude or so more complicated. I would not even think about creating those in PASM.
  • HarpritHarprit Posts: 539
    edited 2013-02-22 06:59
    Thanks guys.

    Now my Responses:

    Yes, I knew you could access the clock from the Special purpose registers at $1F1 and as CNT but I had forgotten about #0 access. Now I wonder about the purpose of having a copy at a writable register at #0. What is the purpose of this?

    I do not program like that! I had made up the spinets to ask the question I needed answered without posting large amounts of code. You will not see such constructs in the book!! But thanks for the good advise.

    If we were to discuss writing a compiler in PASM, it would be about how to write the compiler in PASM and not about writing a compiler in PASM. The discussion of such a problem would greatly enhance one's knowledge about PASM. Climbing Everest v/s knowing how to climb Everest. Then you can climb any mountain. Well, maybe be not.

    And now the confession. Yes it was about arrays and my brain is still pretty much MT on the subject. Specifically I was was interested in two aspects of the problem. How to enter the data for an array into the program and two how to access it properly. Say I have an array of over 150 constants (which is getting big for a small logic engine like the Prop). What is the best way and least tedious way to put these into the DAT area and what is the best way to access them on a random basis, meaning not serially. They need to be placed in in three areas. In the program under DAT. In the hub memory as referable by PAR and in the cog memory and accessed in, how I still don't know. How does one move between the three, meaning how does one tie it all into the PAR reference in a smooth and competent way?

    This is about the last problem in getting the book done. Phew.

    Its easy enough in SPIN.
    H
  • HarpritHarprit Posts: 539
    edited 2013-02-22 08:02
    I was not going to cover packing values into longs just yet
    H
  • Heater.Heater. Posts: 21,230
    edited 2013-02-22 08:09
    Can't code it for you just now but if you have an "array" of constants in DAT like so:

    constants LONG 32, 43, 435, 66, 6

    You can read the first one with:
    mov     someThing, constants
    

    If you want to get the next one in the list you have a little problem as PASM does not have indexed addressing.
    What you do is write the required source address into that move instruction to force it to pick up the right one. Something like:
            mov     ptr, #constants    ' Get the COG address of constants into ptr
            add     ptr,2               ' Offset to third item in the constans array
            movs    ins, ptr          ' Change the instruction at "ins" below to address that element
            nop                          ' We need a nop to allow for the CPU pipeline.
    ins     mov     something, 0   ' When we get here we are actually doing a "mov something, (constants + 2)
    

    Well something like that. Others here were correct me I'm sure.
    Of course that "2" above could be some register holding an varying index value.
  • HarpritHarprit Posts: 539
    edited 2013-02-22 12:26
    Heater:

    If I may I'd like to see how you would code it
    10 variables
    No hurry

    H
  • tonyp12tonyp12 Posts: 1,951
    edited 2013-02-22 12:57
    No need to use temporary ptr
            movs    ins, #constants 
            add     ins, #2            ' Offset to third item in the constans array
            nop                        ' We need a nop to allow for the CPU pipeline.
    ins     mov     something, 0-0     ' When we get here we are actually doing a "mov something, (constants + 2)
    


    >Now I wonder about the purpose of having a copy at a writable register at #0. What is the purpose of this?
    That is Hub address 0, it stores the Spin value: clkfreq (how many ticks in one second)
  • HarpritHarprit Posts: 539
    edited 2013-02-23 12:53
    Take a look at this code.

    The SPIN part of the program program display 8 HUB
    location on the PST so you can see what is going on.

    The PASM part toggles pin1 based on the value in Par/Hub(0)
    which is a potentiometer.

    In this program if I change the value that is passed to the DJNZ
    loop from #500 to "reading", ("reading" was read from hub(0))
    the pin will not toggle and the value "reading" will not be
    written to the mem6 PAR referenced location.

    What happens in the subroutine "Be_d" should not affect
    the transfer of reading into mem6 location.

    Please explain what I am doing wrong.

    H
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000  
      vars=8
       
    OBJ 
      fds : "FullDuplexSerial"         'for communications with PST
      r4p : "read4Pots"
      
    VAR  
      long P_Val[vars] 
      byte subsc
      
    PUB Main|x 
    fds.start(31,30,0,115200)       'start console at 115200 for debug output '
    r4p.Read4Pots(@P_Val)           '
    waitcnt(clkfreq/100+cnt)        'wait for startup '
    Cognew(@beats,   @P_Val)        
    waitcnt(clkfreq/100+cnt)        'wait for startup '
      repeat                        '
        fds.tx($1)                  'home to 0,0
        fds.str(string("Data display"))  'print to display
        fds.str(string("   "))      'spaces to erase old data overflow
        fds.tx($d)                  'new line
        fds.tx($d)                  'new line
        repeat subsc from 0 to vars-1
          if subsc==4 
            fds.tx($d)              'new line spaces first 4 values apart 
          fds.dec(subsc)                            
          fds.str(string("   "))    '
          fds.dec(P_Val[subsc])     '
          fds.str(string("   "))    '
          fds.tx($d)                'new line
        fds.tx($d)                  'new line                                             
        fds.str(string("4 potentiometers and"))  'print to display
        fds.tx($d)                  'new line 
        fds.str(string("rest of misc variables"))'print to display 
        fds.tx($d)                  'new line 
        fds.str(string("Beats = "))'print to display
        fds.dec((P_Val[0]+19)/24+40)
        P_Val[4]:=((P_Val[0]+19)/24+40)
        P_Val[5]:=800000/((P_Val[0]+19)/24+40)
        waitcnt(clkfreq/60+cnt)       'flicker free wait
        x:=x+1          'increment counter. (This routine clears up the screen )
        if x>10         'decision point     (by erasing extraneous lines of bottom )
          fds.tx(16)    'clear screen       (of PST display every 10 loops )
          x:=0          'reset counter                             
    
    DAT       org     0
    Beats     mov     dira,     set_Dira    'Set up DIRA
              mov     mem,      par         '                                                   
              mov     mem4,     mem         '
              add     mem4,     #16         '          
              mov     mem5,     mem         '
              add     mem5,     #20         '         
              mov     mem6,     mem         '
              add     mem6,     #24         '
              nop
              nop
              nop
              
    reread    rdlong reading,   mem5        'Read location 0   
              wrlong reading,   mem6        'Write it to location 6 XXXXXXXXXXXX  the transfer that messes up   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
              or      outa,     pin1        'pin1 high
              call    #Be_d                 'call delay
              andn    outa,     pin1        'pin1 low
              call    #Be_d                 'call delay
              jmp     #reread               'loop back and read again
    '=============================
    Be_d      mov     pass,    #500                   ' XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX problem area when #500 changed to 'readiing'    XXXXXXXXXXXX           
    :loop     djnz    pass,    #:loop       '                      
    Be_d_ret  ret                           '
    '===============================        ' 
    set_dira  long %00001011_00000000_00000000_00000011
    pin1      long %00000000_00000000_00000000_00000010
    '===============================================================================
    mem       res 1
    mem4      res 1 
    mem5      res 1 
    mem6      res 1
    
    mem0      res 1
    mem04     res 1 
    mem05     res 1
    
    reading   res 1
    pass      res 1
    ldelay    res 1
                                                          
    FIT
    
  • HarpritHarprit Posts: 539
    edited 2013-02-23 13:21
    Seems like even adding 1 to "reading" fixes the problem
    and I can make it come and go
    (The absolute test for a fix)
    I tried adding nops all over the place and that does not work.
    But why. Why should adding just 1 work.

    And when does one have to add a 1
    Be_d           
    add reading, #1   'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  here  XXXXXX
    mov      pass,    reading                '             
    :loop     djnz    pass,    #:loop       '                      
    Be_d_ret  ret                           '
    

    H
Sign In or Register to comment.