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

Propeller Assembly for beginners

1141517192029

Comments

  • HarpritHarprit Posts: 539
    edited 2011-12-11 13:31
    Progress report

    I have chapter 1 on outputs pretty well in hand and I have a couple of three other chapters on things like the PAR function and reading potentiometers well along. I am on the chapter on inputs and interaction with the outputs that were learned in chapter 1. I have sketches on the drawings but there are not all in the text yet. Programs inserted but not yet polished and fully commented. I have about 120 pages done or about a third of the book. I think I'll be done by late spring.

    Its moving along pretty good. Better than I thought but then again this should be the easy part!

    I have not at all been impressed by the couple of books I bought as e-books. I found it extremely hard to jump back and forth for looking stuff up (which you need to do a lot in a technical beginner's book). Am thinking about providing hard copy only which could be done for about $20.00 postpaid if I don't let Amazon in on it. I'm still open on this one and I welcome comments on this so I can see what every one wants done.

    H
  • photomankcphotomankc Posts: 943
    edited 2011-12-12 06:23
    I'm an E-Book fan now. Being able to just pop out the IPad and pick up reading at lunch or after dinner at a relative's house is nice and as long as the TOC is fairly well laid out I can get back and forth well enough. Not sure what overhead or fees it adds to put something in that format but I have been buying up E-Books like crazy of late and I'd love to see more techincal stuff availible out there.
  • HarpritHarprit Posts: 539
    edited 2011-12-23 09:13
    This is about the MCP 3208 A to D chip reading 4 pots

    I have a program in which I set the address for the 3 lines that select the channel to read directly thus
                 andn       outa ,   din_Bit        'makes Din low  000 for line 0
                  call        #Tog_Clk                'toggle clock line hi-low to read data          
                  andn      outa ,   din_Bit        'makes Din low  000 for line 0
                  call        #Tog_Clk                'toggle clock line hi-low to read data           
                  andn      outa ,   din_Bit        'makes Din low  000 for line 0
                  call       #Tog_Clk                 'toggle clock line hi-low to read data
    
    The above would read channel 0 on the IC
    and it reads all 12 bits just fine every time

    If I do this with subroutines thus
                  call   #Set_next_bit0
                  call   #Set_next_bit0
                   call   #Set_next_bit0
    
    with the subroutines as follows
    Set_next_bit0  andn      outa ,   din_Bit        'makes Din low  
                          call      #Tog_Clk                   'toggle clock line hi-low to read data              
    Set_next_bit0_ret        ret                            'return from this subroutine
    
    Set_next_bit1    or      outa ,   din_Bit           'makes Din hi 
                  call      #Tog_Clk                           'toggle clock line hi-low to read data              
    Set_next_bit1_ret        ret                            'return from this subroutine
    

    It seems to read all 12 bits and then if I play with the pot
    it reads the two least significant bits as 0s
    If I set it up to read 11 bits or less everything is fine

    I went through the code and the rest is identical in both programs
    I even printed both programs out and checked them a line at a time.

    The reason I want to use subroutines it to allow me to read all 8 channels from one cog in PASM.
    I've been at it for two days. It is very repeatable.

    Any ideas, comments or solutions? Has anyone seen this.

    H
  • JonnyMacJonnyMac Posts: 9,161
    edited 2011-12-23 12:30
    I've attached my own high-speed MCP3208 object (which is used in commercial apps) -- it may be of use to your learning process. Note that I only use single-ended mode and the program is designed accordingly.
  • HarpritHarprit Posts: 539
    edited 2011-12-26 16:29
    Thanks J/M
    Will study it.
    H
  • HarpritHarprit Posts: 539
    edited 2011-12-27 12:42
    A Spin cog starts a second PASM cog
    The PASM cog stores 4 values in hub memory with Par and offsets of 4 each etc
    I can read and display the 4 values from the SPIN cog just fine.
    So far so good

    Then I start a third PASM cog to blink an LED
    The LED blinks just fine
    I can no longer read the values I had in hub memory
    They are all 0s

    What gives?
    {{
    022 PASM Read4Pots.spin
    Program to read 4 pots
    Repeats the program GOOD 006 PASM ReadPot 4 times
    Installs in separate cog.
    Reads resistances to 12 bits appears in POT_RES global variable
    15 Dec 2011
    By Harprit Sandhu
    }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      bits=12
      pots=4
      
    VAR
      long  P_Val[8]
      long  pot_sub
      long  clear
      
    OBJ                                                            
      fds : "FullDuplexSerial"
      
    PUB Main                            'P_VAL is a local variable here
    fds.start(31,30,0,115200)           'start console at 115200 for debug output       
    cognew(@generate, @P_Val)           'start new cog at "generate", read var to P_Val 
    cognew(@tone, 0)                    'start new cog at "tone", read var to P_Val
    waitcnt(clkfreq/4+cnt)
      repeat                            'endless loop
        pot_sub:=0                      'reset id of pot to be printed
        fds.tx($1)                      'home to 0,0
        repeat pots                     'loop to display data
          fds.bin(P_val[pot_sub], bits) 'print to the PST in binary                                 
          repeat 2                      'two spaces                                                          
            fds.tx(" ")                 'space to erase old data overflow        
          fds.dec(P_val[pot_sub])       'print value as decimal value     
          repeat 2                      'two spaces
            fds.tx(" ")                 'space to erase old data overflow        
          fds.dec(pot_sub)              'print value as decimal value     
          repeat 3                      'three spaces
            fds.tx(" ")                 'space to erase old data overflow
          fds.tx($d)                    'new line
          pot_sub:=pot_sub+1            'increment display counter
        waitcnt(clkfreq/60+cnt)         'flicker free wait
        clear:=clear+1                  'increment counter. This routine clears up screen
        if clear>10                     'decision point     by erasing extra lines of bot
          fds.tx(16)                    'clear screen       of PST display every 10 loops
          clear:=0                      'reset counter                    
    DAT           org       0                       'sets the starting point in Cog
                  'first set up all the counters and addresses needed
    generate      mov       pots_read, #8           'number of pots to read [also change data]
                  mov       bits_read, #12          'bit resolution of 3208 IC, can be less
                  mov       mem,       par          'get address of mem for PAR
                  mov       dira,      set_dira     'sets direction of the prop pins
                  mov       pot_id,    #0           'first pot read is pot 0
                  'inner loop for each pot 
    gen2          or        outa ,   chs_Bit        'makes Chip select high
                  andn      outa,    chs_Bit        'makes chip select low 
                  andn      outa ,   clk_bit        'ANDN it with the Clock Bit to make low
                  or        outa ,   din_Bit        'makes the Din high
                  call      #Tog_clk                'toggle clock line hi-low to read data
                  or        outa ,   din_Bit        'makes the Din high 
                  call      #Tog_Clk                'toggle clock line hi-low to read data
                  'set three bit address of current pot
                  mov       temp2,     pot_id       'we will read three bits from this pot
                  call      #get_third_bit          'get bit
           if_nz  jmp       #its_one                'jump to set it as needed
                  jmp       #its_zero               'jump to set it as needed
    its_one       call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue1              'go to next bit
    its_zero      call      #Set_next_bit0          'setting bit subroutine call
    continue1     call      #get_second_bit         'get bit
           if_nz  jmp       #its_one1               'jump to set it as needed
                  jmp       #its_zero1              'jump to set it as needed
    its_one1      call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue2              'go to next bit
    its_zero1     call      #Set_next_bit0          'setting bit subroutine call
    continue2     call      #get_first_bit          'get bit
           if_nz  jmp       #its_one2               'jump to set it as needed
                  jmp       #its_zero2              'jump to set it as needed
    its_one2      call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue3              'go to next bit
    its_zero2     call      #Set_next_bit0          'setting bit subroutine call
                  'finish transfer of data to the porpeller
    continue3     andn      outa ,   din_Bit        'makes Din low              
                  call      #Tog_Clk                'toggle clock line hi-low to read data
                  call      #Tog_Clk                'toggle clock line hi-low to read data                        
                  mov       dat_red,  #0            'clear register we will read data into             
                  mov       bit_count, bits_read    'counter for number of bits we will read
    read_bit      mov       temp,     ina           'read in what is in all the input lines
                  andn      temp,     mask26 wz     'mask off except Dout line. Set Z flag    
                  shl       Dat_red,  #1            'shift register left 1 bit for next bit
            if_nz add       Dat_red,  #1            'if value + add 1 to data register    
                  call      #Tog_Clk                'toggle clock get next bit ready in Dout
                  sub       bit_count, #1 wz        'decr the "bits read" counter. Set Z flag
            if_nz jmp       #read_bit               'go up do it again if counter not yet 0 
                  wrlong    Dat_red,  mem           'write it in PAR to share it as P.Val
                  add       mem,  #4                'add 4 to hub address for next long
                  add       pot_id, #1              'so we can look at next pot
                  mov       temp2, pot_id           'recall what pot we are reading
                  sub       temp2, pots_Read   wz   'check if it is how many we want to read
                  'jump back up to appropriate spot
          if_nz   jmp       #gen2                   'if it is not 0 go up and read next pot
                  jmp       #generate               'go back beginning and do all pots again
     
    tone          org 0
                  mov       dira,      set_dira     'sets direction of the prop pins
                  mov       outa,      set_dira
                 ' mov       mem,       par          'get address of mem for PAR
                  mov       delay,     cnt                                       
                  add       delay,     #16
    :loop         or        outa,      test_bit
                  waitcnt   delay,     seconds
                  andn      outa,      test_bit
                  waitcnt   delay,     seconds  
                  'rdlong    seconds,     mem
                  'shl       seconds,     #1
                  jmp       #:loop           
                                    
    
                  
    'subroutines used
    Set_next_bit0  andn     outa ,    din_Bit       'makes Din low in 000 for line
                  call      #Tog_Clk                'toggle clock line hi-low to read data              
    Set_next_bit0_ret       ret                     'return from this subroutine
    
    Set_next_bit1 or        outa ,    din_Bit       'makes Din high in 000 for line
                  call      #Tog_Clk                'toggle clock line hi-low to read data              
    Set_next_bit1_ret       ret                     'return from this subroutine
    
    Tog_Clk       nop                               'nop to settle signals
                  or        outa,      clk_bit      'make clock bit high
                  nop                               'nop to settle signals
                  andn      outa,      clk_bit      'make clock bit low
                  nop                               'nop to settle signals
    Tog_Clk_ret   ret                               'return from this subroutine         
    
    Get_first_bit  mov      temp2,     pot_id       'get current pot number
                   andn     temp2,     mask0   wz     'get last bit
    Get_first_bit_ret       ret                     'return
    
    Get_second_bit mov      temp2,     pot_id       'get current pot number
                   shr      temp2,     #1           'shift right 1 bit to get second bit
                   andn     temp2,     mask0   wz     'mask 0 bit  
    Get_second_bit_ret      ret                     'return 
                                                    
    Get_third_bit  mov      temp2,     pot_id       'get current pot number
                   shr      temp2,     #2           'shift right 2 bits to get third bit
                   andn     temp2,     mask0    wz    'mask 0 bit 
    Get_third_bit_ret        ret                    'return
    
    Set_dira      long      %00001011_00000000_00000000_00001111   'Set dira register                                 
    Chs_Bit       long      %00000001_00000000_00000000_00000000   'Chip select bit     24
    Din_Bit       long      %00000010_00000000_00000000_00000000   'Data in bit         25
    Dout_Bit      long      %00000100_00000000_00000000_00000000   'Data out bit        26
    Clk_Bit       long      %00001000_00000000_00000000_00000000   'Clock bit           27
    mask26        long      %11111011_11111111_11111111_11111111   'Mask to read Dout bit
    mask0         long      %11111111_11111111_11111111_11111110   'Mask to read 0 bit    
    test_bit      long      %00000000_00000000_00000000_00000011   '
    seconds       long      10_000_000 
    
    temp           res      1       'temporary storage variable, misc  
    temp2          res      1       'temporary storage variable, misc
    bit_count      res      1       'temporary storage variable, read bit counter
    Dat_Red        res      1       'temporary storage variable, data being read
    mem            res      1       'memory location for PAR variable
    pot_id         res      1       'current pot id number
    pots_read      res      1       'total number of pots to be read.
    bits_Read      res      1       'resolution of data read, 12 bits max
    delay   res 1
    potval res 1
    'seconds res 1
    
    H
  • HarpritHarprit Posts: 539
    edited 2011-12-27 14:33
    What I am really asking is
    Where did I go wrong writing to hub in one PASM cog
    and reading the data from a second PASM cog
    or if you will
    How does one do this right?
    H
  • Heater.Heater. Posts: 21,230
    edited 2011-12-27 15:22
    I haven't looked too hard at that code but I notice your PASM function generate uses subroutines that are after the "org 0" statement for your PASM tome function.
    Those subroutines in turn use variables even further down the listing.
    This all looks very suspicious to me.
    Due to that second org the subrouines are assembled as if they are in a different COG location than they actually are when loaded into COG.
    Can't see how that is going to work.
  • JonnyMacJonnyMac Posts: 9,161
    edited 2011-12-27 15:41
    Where did I go wrong writing to hub in one PASM cog
    and reading the data from a second PASM cog

    I haven't looked at your code but here's what you should check: both cogs know the address to be used. When you start each cog you will want to pass an address the hub that Cog 1 writes to and Cog #2 reads from. The key is that the setup cog (Cog #0, if you will) makes that decision and passes the common address to the others.

    [Edit] Okay, I just looked. You're passing 0 instead of the hub address to your "tone" cog, and within that code you've comment out the line that picks up the hub address from the par register.
  • HarpritHarprit Posts: 539
    edited 2011-12-28 08:45
    J/M

    I can get the blinking working with the revised code. See below
    but the variables in hub go to 0 as soon as I start the 3rd cog in PASM

    I moved the 3rd cog down and separated out all its variables so they are
    below it. Variable for the two PASM cogs now are under the code for each of them
    However, since variable names cannot be repeated each hub has to use unique
    variable names. I did that. I added dira and outa descriptions for the last cog.

    H
    {{
    022 PASM Read4Pots.spin
    Program to read 4 pots
    Repeats the program GOOD 006 PASM ReadPot 4 times
    Installs in separate cog.
    Reads resistances to 12 bits appears in POT_RES global variable
    15 Dec 2011
    By Harprit Sandhu
    }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      bits=12
      pots=4
      
    VAR
      long P_Val[8]
      long  pot_sub
      long  clear
      
    OBJ                                                            
      fds : "FullDuplexSerial"
      
    PUB Main                            'P_VAL is a local variable here
    fds.start(31,30,0,115200)           'start console at 115200 for debug output       
    cognew(@generate, @P_Val)           'start new cog at "generate", read var to P_Val 
    cognew(@tone, @P_Val)               'start new cog at "tone", read var to P_Val
    waitcnt(clkfreq/4 +cnt)
      repeat                            'endless loop
        pot_sub:=0                      'reset id of pot to be printed
        fds.tx($1)                      'home to 0,0
        repeat pots                     'loop to display data
          fds.bin(P_val[pot_sub], bits) 'print to the PST in binary                                 
          repeat 2                      'two spaces                                                          
            fds.tx(" ")                 'space to erase old data overflow        
          fds.dec(P_val[pot_sub])       'print value as decimal value     
          repeat 2                      'two spaces
            fds.tx(" ")                 'space to erase old data overflow        
          fds.dec(pot_sub)              'print value as decimal value     
          repeat 3                      'three spaces
            fds.tx(" ")                 'space to erase old data overflow
          fds.tx($d)                    'new line
          pot_sub:=pot_sub+1            'increment display counter
        waitcnt(clkfreq/60+cnt)         'flicker free wait
        clear:=clear+1                  'increment counter. This routine clears up screen
        if clear>10                     'decision point     by erasing extra lines of bot
          fds.tx(16)                    'clear screen       of PST display every 10 loops
          clear:=0                      'reset counter
          
    DAT         
                                                      
    
    generate    org 0                 'sets the starting point in Cog
                  'first set up all the counters and addresses needed
                  mov       pots_read, #8           'number of pots to read [also change data]
                  mov       bits_read, #12          'bit resolution of 3208 IC, can be less
                  mov       mem,       par          'get address of mem for PAR
                  mov       dira,      set_dira     'sets direction of the prop pins
                  mov       pot_id,    #0           'first pot read is pot 0
                   
    gen2          or        outa ,   chs_Bit        'makes Chip select high
                  andn      outa,    chs_Bit        'makes chip select low 
                  andn      outa ,   clk_bit        'ANDN it with the Clock Bit to make low
                  or        outa ,   din_Bit        'makes the Din high
                  call      #Tog_clk                'toggle clock line hi-low to read data
                  or        outa ,   din_Bit        'makes the Din high 
                  call      #Tog_Clk                'toggle clock line hi-low to read data
                  
                  mov       temp2,     pot_id       'we will read three bits from this pot
                  call      #get_third_bit          'get bit
           if_nz  jmp       #its_one                'jump to set it as needed
                  jmp       #its_zero               'jump to set it as needed
    its_one       call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue1              'go to next bit
    its_zero      call      #Set_next_bit0          'setting bit subroutine call
    continue1     call      #get_second_bit         'get bit
           if_nz  jmp       #its_one1               'jump to set it as needed
                  jmp       #its_zero1              'jump to set it as needed
    its_one1      call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue2              'go to next bit
    its_zero1     call      #Set_next_bit0          'setting bit subroutine call
    continue2     call      #get_first_bit          'get bit
           if_nz  jmp       #its_one2               'jump to set it as needed
                  jmp       #its_zero2              'jump to set it as needed
    its_one2      call      #Set_next_bit1          'setting bit subroutine call
                  jmp       #continue3              'go to next bit
    its_zero2     call      #Set_next_bit0          'setting bit subroutine call
    
    continue3     andn      outa ,   din_Bit        'makes Din low              
                  call      #Tog_Clk                'toggle clock line hi-low to read data
                  call      #Tog_Clk                'toggle clock line hi-low to read data                        
                  mov       dat_red,  #0            'clear register we will read data into             
                  mov       bit_count, bits_read    'counter for number of bits we will read
    read_bit      mov       temp,     ina           'read in what is in all the input lines
                  andn      temp,     mask26 wz     'mask off except Dout line. Set Z flag    
                  shl       Dat_red,  #1            'shift register left 1 bit for next bit
            if_nz add       Dat_red,  #1            'if value + add 1 to data register    
                  call      #Tog_Clk                'toggle clock get next bit ready in Dout
                  sub       bit_count, #1 wz        'decr the "bits read" counter. Set Z flag
            if_nz jmp       #read_bit               'go up do it again if counter not yet 0 
                  wrlong    Dat_red,  mem           'write it in PAR to share it as P.Val
                  add       mem,  #4                'add 4 to hub address for next long
                  add       pot_id, #1              'so we can look at next pot
                  mov       temp2, pot_id           'recall what pot we are reading
                  sub       temp2, pots_Read   wz   'check if it is how many we want to read
          if_nz   jmp       #gen2                   'if it is not 0 go up and read next pot
                  jmp       #generate               'go back beginning and do all pots again
    
    
                  
    'subroutines used
    Set_next_bit0  andn     outa ,    din_Bit       'makes Din low in 000 for line
                  call      #Tog_Clk                'toggle clock line hi-low to read data              
    Set_next_bit0_ret       ret                     'return from this subroutine
    
    Set_next_bit1 or        outa ,    din_Bit       'makes Din high in 000 for line
                  call      #Tog_Clk                'toggle clock line hi-low to read data              
    Set_next_bit1_ret       ret                     'return from this subroutine
    
    Tog_Clk       nop                               'nop to settle signals
                  or        outa,      clk_bit      'make clock bit high
                  nop                               'nop to settle signals
                  andn      outa,      clk_bit      'make clock bit low
                  nop                               'nop to settle signals
    Tog_Clk_ret   ret                               'return from this subroutine         
    
    Get_first_bit
                   mov      temp2,     pot_id       'get current pot number
                   andn     temp2,     mask0 wz     'get last bit
    Get_first_bit_ret       ret                     'return
    
    Get_second_bit
                   mov      temp2,     pot_id       'get current pot number
                   shr      temp2,     #1           'shift right 1 bit to get second bit
                   andn     temp2,     mask0 wz     'return   
    Get_second_bit_ret      ret                
    
    Get_third_bit        
                   mov      temp2,     pot_id       'get current pot number
                   shr      temp2,     #2           'shift right 2 bits to get third bit
                   andn     temp2,     mask0 wz     'return 
    Get_third_bit_ret        ret 
     
    Set_dira      long      %00001011_00000000_00000000_00001111   'Set dira register                                 
    Chs_Bit       long      %00000001_00000000_00000000_00000000   'Chip select bit     24
    Din_Bit       long      %00000010_00000000_00000000_00000000   'Data in bit         25
    Dout_Bit      long      %00000100_00000000_00000000_00000000   'Data out bit        26
    Clk_Bit       long      %00001000_00000000_00000000_00000000   'Clock bit           27
    mask26        long      %11111011_11111111_11111111_11111111   'Mask to read Dout bit
    mask0         long      %11111111_11111111_11111111_11111110   'Mask to read 0 bit                                                                                         
    
    mem            res      1
    temp           res      1          'temporary storage variable, misc
    temp2          res      1       'temporary storage variable, misc
    bit_count      res      1       'temporary storage variable, read bit counter
    Dat_Red        res      1       'temporary storage variable, data being read 
    pot_id         res      1       'current pot id number
    pots_read      res      1       'total number of pots to be read.
    bits_Read      res      1       'resolution of data read, 12 bits max
    
    '---------------------------------------------------
    tone          org       0                                            
                  mov       dira,      set_dirq     'sets direction of the prop pins
                  mov       outa,      set_dirq     'sets direction of the prop pins  
                  mov       mem9,      par
                  mov       delay,     cnt
                  add       delay,     #16
    loop          or        outa,      test_bit
                  waitcnt   delay,     seconds
                  andn      outa,      test_bit
                  waitcnt   delay,     seconds
                  jmp       #loop
                  
    Set_dirq      long      %00001011_00000000_00000000_00001111   'Set dira register  
    test_bit      long      %00000000_00000000_00000000_00000011
    seconds       long      8_000_000                                                    
                                             
    mem9           res      1       'memory location for PAR variable
    delay          res      1    
    
    
  • HarpritHarprit Posts: 539
    edited 2011-12-28 13:32
    Here is the answer after about three days of banging my head against the wall
    and adding and deleting code a line at a time. Very tedious but I learned a lot

    Many many thanks to JonnyMac and Heater.

    NOT EVERYTHING I SAID HERE MIGHT BE 100% RIGHT
    (REMEMBER I AM A BEGINNER!)
    Need expert commentary and discussion on all this, please.

    Here are my discoveries:
    Each cog has to define the dira register identically
    All shared variables have to be called in all cogs identically.
    You cannot read more than 8 cogs from the MCP 3208 without getting in trouble.
    You cannot display more pots than you actually read or there will be problems
    Each cog has to be defined after everything for the previous cog has been defined.
    Meaning constants and variables.
    For a reason I do not understand. PASM does not isolate variables within each cog.
    Each cog has to use different names for its variables. You cannot repeat variable form cog to cog
    Then it works, maybe!!

    On to the next chapter!!

    H
  • JonnyMacJonnyMac Posts: 9,161
    edited 2011-12-28 16:03
    Some thoughts:
    Each cog has to define the dira register identically

    Not so. This would be true if you want separate cogs to have output control over the same pin. There is a danger with this, however, because if one cog drives an output pin high it doesn't matter what the other cogs do, that pin will be high.

    All shared variables have to be called in all cogs identically.

    Shared variables indicate in the hub, hence there is only one way to call them (from PASM with rdlong, rdword, rdbyte). In order to share hub variables, each cog using a particular variable must know that variable's hub address.

    You cannot read more than 8 cogs from the MCP 3208 without getting in trouble.

    Unsure by what you mean with this; the MCP3208 is an eight-channel device, and there are only eight cogs in the Propeller. "More than 8" is a bit of a mystery....

    You cannot display more pots than you actually read or there will be problems

    And you can't wash windows you don't actually have.... ;) You can always display the last reading of any sensor, and you don't have to read all sensors (or device channels) every time.

    For a reason I do not understand. PASM does not isolate variables within each cog.
    Each cog has to use different names for its variables. You cannot repeat variable form cog to cog

    If you put more than one PASM section into an object file you will be limited. The key is to use a well-crafted wrapper to launch your PASM code that can be placed in its own file. That way you get easy re-use (no copy and paste) and you don't have variable name issues -- most of the time. Fair warning: within an object file you'll want to be careful not to re-use names for global variables in your PASM section.


    I know I keep harping on this but your desire to do things in what you believe is an "easy" way instead of the correct way causes you all sorts of unnecessary frustration.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-28 16:54
    I think it is quite reasonable that using the same label twice in a source file is not allowed. No matter which COGs that code actually ends up running in, after all the compiler is not able to actually know which COG the code will be run in ultimately. I'm sure most assembly languages work this way. The idea of "scope" like that is mostly a high level language feature (local variables to functions for example). The PASM local vars with ":" is something I have never see elsewhere.

    I agree with Jon, it's almost always better to put the PASM sections into different source files. Especially if they have unrelated functionality.
  • HarpritHarprit Posts: 539
    edited 2011-12-29 08:44
    Heater:

    "put the PASM sections into different source files"

    Please explain to me exactly what you mean by this so that I can do it right.
    I thought that was what I did but apparently I am not. Confusion caused by my lack of
    experience with formal assembly language jargon.

    Thanks
    H
  • JonnyMacJonnyMac Posts: 9,161
    edited 2011-12-29 09:20
    The MCP3208 object I posted above is an example of putting PASM code into its own file with Spin interface methods for that code. Typically, objects use a method called .start() to accept any parameters and launch the PASM code into its own cog. Many (if not most) objects that launch a PASM driver include a .stop() method to kill the PASM cog if that is ever required.

    In the case where you want to create an object that uses shared hub memory you can pass the desired hub address as a parameter in the .start() method. Again, if you look at my MCP3208 object posted above you'll see that I'm doing that (the fourth parameter, dest, is the destination address for the ADC readings). The way that I constructed this object allows my client program to specify the address of an array of longs in the .start() method and then never have to manually call the object again. The design of the object causes the ADC to continuously read and place those readings at the target location in the hub. From the user prospective, there is a set of variables that update themselves based on the inputs to the ADC.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-29 11:24
    Harprit,

    Nothing complicated.

    "source code" is the human readable text of the program as we type into the Prop Tool or whatever editor.
    As opposed to the compiled "binary code" or "object code" which is what is loaded into a computer when we want to run it.

    So "source file" is simply a normal file that contains source code.

    A feature of Spin is that a single source file is used to define a single Spin object. You can't have two or more Spin objects in a file and you can't have a Spin object spanning over more than one file. Unlike C++, say, where many classes can be written in a single file or the methods of a class can be in different files if need be.

    So in Spin each object is contained within a single source file. This includes the all the Spin methods of the object and any PASM that object may want to start in a COG.

    So now: It is good programming practice to separate different functionality into different objects. So for example a UART goes into FullDuplexSerial.spin and your LED flasher code goes into LedFlasher.spin. The UART object contains nothing pertaining to LEDS and the LED object knows nothing about serial communications. This makes for easier to read code, helps make the different components reusable in other projects and has other benefits.

    One of those other benefits is in code "maintainance". If you fix or change one are of functionality it is not going to break another because it is in its own module (Spin object / source file). You only have to ensure the memory interfaces used for communication between objects remains consistent. I belive this is the issue you have been fighting with here.

    It makes sense therefore to put PASM code of different functionality into its own Spin object (source file) with a little Spin wrapper to start it in a a COG and perhaps stop it. Even if there is no other use Spin in that mainly PASM source file.

    This way you have no worries about duplicate label names within a file. Or confusions about ORG etc etc.

    As always there are times when there is a good reason to break these simple guidelines but I don't think we are there yet.
  • HarpritHarprit Posts: 539
    edited 2011-12-29 14:07
    Ok guys,
    Let me see if I got this right. I'm beating it down to the basics I can write up

    What I did was use the SPIN cog to display to the data on the PST
    and start two other cogs from the spin cog as PASM cogs 1 and 2.

    Are you saying that the two PASM cogs should be set up as independent
    cogs started from their own SPIN program and then put these in the files on disk as independent files
    Then read them in as OBJ files used in my program.

    H
  • Heater.Heater. Posts: 21,230
    edited 2011-12-29 15:06
    Yes.
    I see it like this:
    1) One main program, however small, in Spin. In it's own file. The top level object. Generally this is the "application"
    2) One or more lower level objects, in this case containing the PASM code we want to start in separate COGS. In their own files.

    That top level objects uses obj statements to enable use of methods in the lower level objects.
    It calls start methods in those lower level objects.
    Those start methods get the PASM going in GOGs with GOGINIT.

    Parameters giving the address(s) of any shared memory blocks for COG to COG communication are passed from top level to start methods to COGNEWs and into PARS as required.

    Result: All your PASM blocks are neatly divided into functional areas, placed in their own objects within their own files.
    No more fighting over duplicate labels or the location of ORGs etc.
  • HarpritHarprit Posts: 539
    edited 2011-12-30 06:53
    First let me state that it is really nice to get two perspectives from two different experienced programmers in that it makes it easier for me to understand what they are trying to tell me. The discussion of the not so good rules that I had formulated, were specially useful in helping me further understand the structure of PASM.

    Thank you JonnyMac and thank you Heater. You guys have been a godsend.

    I will break the code up as suggested later today and see how it works. I need to get used to doing it this way. I will also have to go back and revise some of the things that I have written to incorporate this more sophisticated way of writing programs. Stuff like this is not really a problem, because I look forward to getting it right.

    Book progress report. As you can probably tell from the level of the program that they are just discussing, I am moving along pretty good on the book. I am now doing the projects that were covered in my SPIN book in PASM. (Right now I am working on the Metronome). They won't be exactly the same, but hopefully useful comparisons will be able to be drawn from the two ways of undertaking these projects. I think, or at least I hope to be done early in spring. What with winter upon us in Illinois, there isn't a whole lot of stuff to do outside and I can concentrate on getting the project wrapped up. Now that I am finally getting a bit of the hang of writing simple stuff in PASM. It's moving a little faster.

    H.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-30 07:39
    If beginners reading your book are anything like me they will be happy to have bits of functionality split into small modules/objects/files. That way you can look at a small part and easily understand it then move on to the next module. If everything is crammed into a single file it gets overwhelming and hard to sort out what is what.
  • JonnyMacJonnyMac Posts: 9,161
    edited 2011-12-30 09:18
    If everything is crammed into a single file it gets overwhelming and hard to sort out what is what.

    Amen. And, frankly, it's a bad habit to teach beginners.
  • HarpritHarprit Posts: 539
    edited 2012-01-02 10:33
    Is this accurate?
    If not what changes are needed


    [FONT=Arial, sans-serif]Before we do anything we need to be aware of the following realities as regards the connections we make to the propeller chip.[/FONT]


    1. [FONT=Arial, sans-serif]The propeller chip is designed to run on 3.3 Volts DC. Though it might tolerate running at 5 VDC power supply for short periods of time. This is absolutely not recommended.[/FONT]
    1. [FONT=Arial, sans-serif]On start up and reset all input lines on the propeller are inputs. These inputs have a high impedance, and can conceivably be connected to five volts DC directly. However it is good practice to protect the chip by using a 1K to 10K ohm resistor in line with the inputs.[/FONT]


    1. [FONT=Arial, sans-serif]If a line is programmed to be an output, and it is shorted to ground, we may have a disaster on our hands in that theoretically an infinite current could now flow to this output line, barring internal resistances. Things could get bad in a hurry! It could lead to the immediate destruction of circuitry internal to this line. Keep this in mind at all times. It is important to (almost always) have at least a 1K resistor in line with all output connections to limit the current and avoid this disaster. If the output connection will not drive the work with a 1K resistor limiting the current, you have to make sure that a shorting condition cannot every occur on the line before making the connection to your hardware.[/FONT]
    Harprit
  • JonnyMacJonnyMac Posts: 9,161
    edited 2012-01-02 10:54
    You might want to be a little careful with generalities; if we follow the datasheet 1K is too low when the input signal is 5V. In Section 7.1 the max forward current through a pin with the protection diode biased is 500uA. In that same table we can see that the forward voltage of the protection diode is 0.3v. At this point, Ohm's Law is our friend:

    (5 - (3.3 + 0.3)) / 0.0005 = 2800

    So... for a 5V input the lowest value should be 2.8K, not 1K as you have now. I tend to use 3.3K in my own designs as that is a standard value; that said, any value higher is fine. In a project I'm doing now I have three other 10K resistors so I used 10K for the input protection to simplify the BOM.
    1024 x 640 - 118K
  • PublisonPublison Posts: 12,366
    edited 2012-01-02 11:04
    Harprit wrote: »
    Is this accurate?
    If not what changes are needed


    Before we do anything we need to be aware of the following realities as regards the connections we make to the propeller chip.

    1. The propeller chip is designed to run on 3.3 Volts DC. Though it might tolerate running at 5 VDC power supply for short periods of time. This is absolutely not recommended.
    Harprit

    That should read "The propeller chip is designed to run on 3.3 Volts DC, 3.6 Volts MAX. NEVER connect the Propeller to 5 Volts
  • PublisonPublison Posts: 12,366
    edited 2012-01-02 11:08
    Harprit wrote: »
    Is this accurate?
    If not what changes are needed


    Before we do anything we need to be aware of the following realities as regards the connections we make to the propeller chip.
    1. On start up and reset all input lines on the propeller are inputs. These inputs have a high impedance, and can conceivably be connected to five volts DC directly. However it is good practice to protect the chip by using a 1K to 10K ohm resistor in line with the input
    Harprit
    [FONT=Arial, sans-serif]
    [/FONT]On start up and reset all I/O PINS on the propeller are inputs.

    Five volts should NEVER be connected to the Input without a resistor.

  • HarpritHarprit Posts: 539
    edited 2012-01-02 12:16
    Publison

    I need to say why we cannot connect 5V to the inputs directly.
    Can you provide verbiage or guidance the I can use that would be suitable for beginners.

    H
  • PublisonPublison Posts: 12,366
    edited 2012-01-02 12:28
    Harprit wrote: »
    Publison

    I need to say why we cannot connect 5V to the inputs directly.
    Can you provide verbiage or guidance the I can use that would be suitable for beginners.

    H

    Jon's post #504 explains it. Direct from the Data Sheet.

    EDIT: The post may help:

    http://forums.parallax.com/showthread.php?85474-How-to-safely-interface-a-5v-signal-to-the-propeller-See-Post-Reply-104&p=585920#post585920

    L
    ots of good stuff in this Sticky:

    http://forums.parallax.com/showthread.php?111166-Propeller-Resource-Index
  • HarpritHarprit Posts: 539
    edited 2012-01-02 13:28
    Thanks
    Regards
    H
  • HarpritHarprit Posts: 539
    edited 2012-01-12 14:31
    What is the proper protocol for reading a variable created in one Cog from another Cog.
    And then using it in the second Cog
    I am including the first cog in the second cog as an OBJ and calling the method that created the value
    I just cant seem to get it right.
    This is all in PASM
    HELP

    H
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-12 17:22
    Please post your current (non-working) sample code. If you ask N people here you'll most likely get M different answers as to how it could be done.
Sign In or Register to comment.