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

Propeller Assembly for beginners

1171820222329

Comments

  • HarpritHarprit Posts: 539
    edited 2012-01-22 13:05
    Steve:
    All my cogs start with the same passed variable but things still get scroggled.
    Maybe every cog ever started has to use the same passed variable even if it is never used
    H
  • jazzedjazzed Posts: 11,803
    edited 2012-01-22 13:17
    Harprit wrote: »
    Steve:
    All my cogs start with the same passed variable but things still get scroggled.
    Maybe every cog ever started has to use the same passed variable even if it is never used
    H
    Generally, It doesn't matter what you pass to PAR with cognew.
    I've only described relationships of PAR and not focused much on your program.
  • frank freedmanfrank freedman Posts: 1,977
    edited 2012-01-22 15:39
    Harprit wrote: »
    @heater

    Ericball answered the question in # 542. Iresponded by mading the corrections and posted to jazzed that everything wored fine for the simp[le programs that I was running. I dont think I am doing thingsany different now!!

    ======

    Well I do think I am getting a handle on things so its not totally blind on my part.

    Here is what I have going

    Program 1
    Reads a potentiometer stores it at Par pointer 1st position. Variable passed is @P_Val
    Performs a division and stores the result in PAR pointer +16 the 5th long location
    One routine displays the data, One stores it via PAR pointers.
    Everything works fine I can read the data and it is what I want where I want it to be.
    Running the program shows everything just right on the PST
    No problems.

    Program 2
    Calls the all of the program in program 1 and everything is fine
    Running the program shows everything just right on the PST
    No problems.

    Next I call just the part of the program that stored the variables in program 1
    I get zeroes.

    All routines that refer to the data use @V_Pal as the passed variable

    Here are the listings you can comment routines out as you see fit.
    {{
    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=8
      
    VAR
      long P_Val[7]
      long  pot_sub
      long  clear
      
    OBJ                                                            
      fds : "FullDuplexSerial"
      
    PUB Main (address)                  'P_VAL is a local variable here
    fds.start(31,30,0,115200)            'start console at 115200 for debug output
    read_Pots(@P_Val)
    dira[0..2]~~
      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*4)            '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
    
    PUB Read_Pots(address)
    cognew(@Read_P, address)
    
    '----------------------------------end of first Cog------------------------------------------
    DAT           org 0                              'sets the starting point in Cog
    Read_P        mov      dira,      set_dira     'sets direction of the prop pi
                  mov       pots_read, #1           '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       mem1, mem
                  mov       pot_id,    #0           'first pot read is pot 0
                   
    Next_pot      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       Data_read,  #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       Data_read,  #1          'shift register left 1 bit for next bit
            if_nz add       Data_read,  #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    Data_read,  mem  wz       'write it in PAR to share it as P.Val
            if_z  jmp #next_pot
                  call #get_beat
    skip          add       mem1,#16
                  wrlong    data_read, mem1 
                  add       mem,  #4                'add 4 to hub address for next long
                  mov       mem1, mem
                  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       #Next_pot               'if it is not 0 go up and read next pot
                  jmp       #Read_P                 '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
    
    Get_beat       mov   temp3,  data_read
                   shl  temp3, #3
                   mov  total, clkf
                   mov  beat, #0
    do_again       sub  total, temp3  wc
                   add  beat,  #1
            if_nc  jmp  #do_again
                   sub  beat,  #1
                   mov   data_read, beat
    Get_beat_ret  ret                              
     
    Set_dira      long      001011_00000000_00000000_00000111   'Set dira register                                 
    Chs_Bit       long      000001_00000000_00000000_00000000   'Chip select bit     24
    Din_Bit       long      000010_00000000_00000000_00000000   'Data in bit         25
    Dout_Bit      long      000100_00000000_00000000_00000000   'Data out bit        26
    Clk_Bit       long      001000_00000000_00000000_00000000   'Clock bit           27
    mask26        long      111011_11111111_11111111_11111111   'Mask to read Dout bit
    mask0         long      111111_11111111_11111111_11111110   'Mask to  read 0  bit                                                                                          
    clkf  long  80_000_000
    
    beat res 1
    mem            res      1       'Par location
    mem1 res 1
    temp           res      1       'temporary storage variable, misc
    temp2          res      1       'temporary storage variable, misc
    temp3 res 1
    bit_count      res      1       'temporary storage variable, read bit counter
    Data_Read      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
    total res 1
    
    
    {
    OSC for metronome
    Read pot and display on PST through 022 PASM Rea4PotsX
    And sets up basic count oscillator
    }
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      'bits=32
    VAR
      long P_Val[7]
    
    obj
      RP : "ReadPots"    'reads pots
      
    PUB Main                           
      dira[0..2]~~
      RP.main(@P_val)
      'RP.read_Pots(@P_val)
      Oscillate (@P_val)                                                                         
      
    PUB Oscillate (address)                        
      cognew(@Oscil, address)
     
    DAT           org       0                                                           
    Oscil         mov       dira,      set_dira       'sets direction of the prop pins
    loop          mov       mem,       par            'get par address
                  add       mem,       #16
                  rdlong    Pot,       mem
                                   
                  mov       delay,     cnt            'read in CNT
                  add       delay,     50             'add to skip over counter fill
                  andn      outa,      bit_1          'bits low
                  waitcnt   delay,     pot            'pause
                  
                  mov       delay,     cnt            'read in CNT
                  add       delay,     50             'add to skip over counter fill
                  or        outa,      bit_1          'bits high
                  waitcnt   delay,     pot            'pause
                  
                  jmp       #loop                     'loop back
    
    Set_dira      long      001011_00000000_00000000_00000111   'Set dira register  
    bit_1         long      000000_00000000_00000000_00000001   'output bit
          
    pot res 1
    mem           res       1          'memory location for PAR variable
    delay         res       1          'delay constant for CNT
    
    

    Harprit.


    Some comments on this code:
    1. waste of memory slots, you move constants into variables to initialize them. A beginner needs to be cognisant of space restrictions. Rather initialize variables where possible at compile time if that is the only time they will be set. Otherwise define your constant and load from it when it is needed.

    Test_pattern long $0f5aa5f0 ' long variable initialized to test pattern at compile time.

    Think of a constant as an initialized variable you will not allow the program to change but only reference.


    2. What is mem1, no comment telling anyone why you have mem1


    3. See comment 1 regarding the reason to set the pot_id to 0 at compile time. If you plan to send the pot id either via par on calling this routine or via mail box that this routine can pick it up from, there is no point in initializing it if you plan to set it to a specific value at run time from the calling program.


    4. Outside of explaining in text that this is kind of what the actual code does, why not write it using loop instructions? This is an ideal example of the power of loops.
    Here is what I used to read out the 12 bits of a 3201 (using separate timbase cog providing signals on cselp, s_val, ):
    dat
    ACQ_mod 'read serial ADC and xfer to parallel output
            org   0
    initval mov     long_ptr,PAR       ' get base address of shared mem
            mov     base_addx,PAR      ' save base
            rdlong  s_val,long_ptr     ' save sample valid
            add     long_ptr,#4        '
            rdlong  smp_dat,long_ptr   ' save sample input valid pin
            add     long_ptr,#4        '
            rdlong  cselp,long_ptr     ' save csel pin
            add     long_ptr,#4        '
            rdlong  dac_out,long_ptr   ' save DAC output range
    'end init
            or      dira,dac_out      ' enable output pins
    main    waitpeq cselp,cselp       ' wait for csel high
            waitpne cselp,cselp       ' when csel goes low, start acq capture/store
    get_val mov   acqvalue,null     ' clear to 0s
            mov   acqcks,#$00f      ' set to get 15 clock times
    acq_bits    waitpeq s_val,s_val ' wait for sample time high
                mov     acq_bld,ina       ' get data bit from input
                test    acq_bld,smp_dat wc  ' see if input pin is high set C
                waitpne s_val,s_val     ' wait for sample to go low
                rcl     acqvalue,#$001    ' rotate in the carry bit
                djnz    acqcks,#acq_bits  ' go get rest of bits
            and   acqvalue,acq_mask       ' mask for lower 12 bits non-zero
            shl   acqvalue,#8      'move to upper bits
            mov   outa,acqvalue       ' putem out
            jmp   #main          ' after all counts,  go back to main and wait.
    
    
    'preset values
    acq_mask long $00000FFF         ' 12 bit mask
    null     long $00000000         '
    
    'var space
    long_ptr      res       1
    base_addx     res       1
    smp_dat       res       1
    s_val         res       1
    cselp         res       1
    dac_out       res       1
    acq_bld       res       1
    acqvalue      res       1
    acqcks        res       1
    
    
    fit $1ef                ' don't let PASM grow beyond $1ef
    
    
    



    5. What you have written may only read the chip because of the way it is written; lots of inherent delay due to the number of instructions used to read the chip. I don't see any provision in your code for assuring the clock signals will meet the minimum timing requirements of the MCP320x family without exceeding the max frequency of the 320x family. Fclk 2mhz max w/ VDD=5V, 1mhz w/ VDD=2.7V. Never a question in spin, but PASMs speed makes that more probable the tighter the loop is written. The worst part is that if it appears to read your beginner may end up tearing their hair out because "it reads, but the values seem random", perhaps because the beginner tried to tighten up this code.

    If I am off the mark on this one I am sure others will jump on this post, but please, try to demonstrate code that is tight and efficient both in execution times and space usage, but not tricky. That will benefit the beginner the most when provided along with appropriate expository texts in the book.

    Your commenting style continues to make great strides, keep it up....

    Frank
  • ChrisGaddChrisGadd Posts: 300
    edited 2012-01-22 16:29
    The first thing that leaps out at me is that you have P_Val defined in both programs. Run on its own, the ReadPots2 program starts the read_Pots method with the local P_Val address, and the Show method displays the value in the local P_val address. When the Oscillator program starts the read_Pots method, it replaces ReadPots2's P_Val address with Oscillator's P_Val address, which is what you want to happen, but the Show method is still displaying values from the P_Val address in ReadPots2.

    As a quick fix, try RP.show(@P_val) in the Oscillator program, and PUB Show(@P_Val) in the ReadPots2 program. More properly, P_Val should only be defined in the parent program, with the address passed to all child programs.

    I'm attaching a couple programs that I wrote when I first tried to understand this behavior. Parent - Archive.zip
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-22 16:58
    Harprit wrote: »
    It should also allow you to look at the 8 PAR longs but it does not. The PST remains blank
    Why do you mention 8 longs? Is the inclusion of pot_sub intentional?

    You do initialise a terminal object in the parent object. How is the show method supposed to know about this? Therefore no output. OK, let's initialise our own private object (and DON'T do this in the parent to avoid pin conflicts).
    {{
    Name this program"ReadPots2"
    }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      bits=12
      pots=8
      
    VAR
      [COLOR="orange"]long  cog[/COLOR]
      long  P_Val[[COLOR="red"]8[/COLOR]]
      long  pot_sub
      long  clear
      
    OBJ                                                            
      fds : "FullDuplexSerial"
      
    PUB Main                            'P_VAL is a local variable here
    read_Pots(@P_Val)
    show
    
    [COLOR="orange"]PRI init
    
      ifnot cog
        cog := fds.start(31, 30, %0000, 115200)[/COLOR]
      
    PUB Show
    
      [COLOR="orange"]init[/COLOR]
      
      repeat                            'endless loop
        pot_sub:=0                      'reset id of pot to be printed
        ...
    
    Now we get PST output. But it's all zero. Think about which P_Val[] show knows about (compared to Read_Pots). Right, it uses its private copy. So change it to obtain the address of the array like you did it for Read_Pots by passing the parent's array address (and change the output statements to use e.g. long[address][] instead of referencing P_Val[] directly).
    DAT           org       0                                                           
    Oscil         mov       dira,      set_dira       'sets direction of the prop pins
    loop          mov       mem,       par            'get par address
                  add       mem,       #16
                  rdlong    Pot,       mem
                                   
    [COLOR="red"]{1}           mov       delay,     cnt            'read in CNT
    {2}           add       delay,     #50            'add to skip over counter fill
    {3}           andn      outa,      bit_1          'bits low
    {4}           waitcnt   delay,     pot            'pause
                  
    {5}           mov       delay,     cnt            'read in CNT
    {6}           add       delay,     #50            'add to skip over counter fill
    {7}           or        outa,      bit_1          'bits high
    {8}           waitcnt   delay,     pot            'pause
    [/COLOR]              
                  jmp       #loop                     'loop back
    
    Set_dira      long      7   'Set dira register  
    bit_1         long      1   'output bit
          
    pot           res       1          'read variable
    mem           res       1          'memory location for PAR variable
    delay         res       1          'delay variable usage
    
    I see you already changed the [#]50 issue. One question though, why 50? You used a great variety of skip values in your examples without ever explaining how you arrived at this value (or why you picked this particular one). I can understand using something big enough (in case the minimum value isn't known) but at least add a comment to that effect (or better yet, understand the issue and use the correct value and refer to an in-depth explanation).

    Anyway, let's ignore that for the moment and have a look at the highlighted code. Assume cnt (line 1) is 42 and pot is 1000. I'd like you to figure out the register values and the instruction effects for all 8 lines (I hope 5 are enough)
  • HarpritHarprit Posts: 539
    edited 2012-01-22 19:05
    @kuroneko

    I will respond to your post in detail after I have digested and understood what you said
    It may take me a day or two.

    H
  • HarpritHarprit Posts: 539
    edited 2012-01-22 19:15
    @Frank and Chris

    Give me a couple of days and I'll try to understand your comments and respond to you accordingly.
    My plate is getting kind of full right now but what with all the help things might be about to be understood by me!

    H
  • HarpritHarprit Posts: 539
    edited 2012-01-23 07:48
    First let me thank every one who has provided me with such tremendous support in this effort. Thank you guys.

    I just read the last two pages (27-29) on the thread to better understand what was going on and one thing came to mind that I need to respond to right away.

    Commenters want me to make the code as fast a possible. Which I am obviously not doing at this time on purpose. I have a very good reason for doing this. The emphasis at this time is to convince the reader that there is nothing intimidating in all this The emphasis is to introduce concepts one at a time as painlessly as possible and not get carried away with concepts either. Vocabulary comes later. Once we understand the basic operations,the grammar as it was, adding vocabulary is easy. I do not subscribe to the idea that bad habits will stick for ever. How many of us program the way we used to as beginners. You will be as good as they want to. PASM is not for everyone by a long shot. (Note my continuing struggle with PAR passed variables and the difficulty the cognoscenti have had explaining it to me in a way I understood right away. Still not there!)

    (I speak English, Hindi, Urdu and Punjabi fluently at native speaker level. I had two years of French in High school and had Russian and German at the University (used to be a PhD requirement). No one started us out writing compact sophisticated suspense novels. It was grammar, grammar, grammar, syntax, syntax, syntax. I know it works. Believe me it works.)

    Also I have been asked to explain the code in more detail at some critical points. I can only do so much in one line of commentary. The rest will be in the body of the text in the book so it will be covered as commenters want. Here we are in complete agreement.

    I will also be including code that has been optimized for speed and shortness in the book but will probably not post much of it here. Just takes time and I am really short on time right now.

    (I looked at iBook Author. Very powerful, WOW software. Am considering working in that format. You do not need an iPad to read the files. They can be published in other formats but might then omit some of the Apple's multimedia whiz bang features not supported by the other formats. In my book we don't need a lot of whiz bang features.)

    H
  • jazzedjazzed Posts: 11,803
    edited 2012-01-23 08:27
    Harprit wrote: »
    Commenters want me to make the code as fast a possible.
    Guess I missed that.

    Communicating a clear understanding of the subject and being able to show the way is vastly more important than writing fast code.
  • ericballericball Posts: 774
    edited 2012-01-23 10:25
    Sorry, trying to show the fastest way possible is no excuse. You need to start with the simplest, easiest to understand techniques, then show how to optimize. Just like in physics you start with the algebraic formulas, then later do the same with calculus & vector calculus.

    I remember one of my first ASM programs was a bubble sort of screen RAM. As I saw how quick the letters on the screen alphabetized themselves I realized how fast ASM could be. I didn't need a quicksort - the bubblesort was just right for a first program.

    I will also say that if you're still stumbling with PAR you have missed some base concepts of how the Propeller works. I suspect you have some unlearning to do.

    The Propeller is made of two types of RAM: 32Kbytes of HUB RAM which is accessible (shared) by all COGs and each COG has 496 longs of private RAM (aka registers). The COGINIT instruction triggers a copy of 496 longs from HUB RAM (or ROM, in the case of the SPIN interpreter) to the private COG RAM. The PAR register is loaded with a 16 bit value (although bits 0 & 1 are always zero) which is usually an address pointer to HUB RAM (in the case of SPIN, this points to the object to be started). The remaining 15 special registers (plus the program counter) are zero'd. Once all of the registers have been loaded, execution starts with register 0.

    Hmmm... just had a thought. We usually consider PAR to be a LONG pointer, but there's no reason it couldn't be used as a WORD pointer:
    coginit( @cogstart, @wordvar << 1)
    
    DAT
             org    0
    cogstart MOV    cogstart, PAR      ' PAR = @wordvar << 1
    wordvar2 SHR    cogstart, #1       ' cogstart = @wordvar
             RDWORD wordvar2, cogstart ' wordvar2 = WORD[@wordvar]
    

    Note: I could have written the code to use separate registers for the RDWORD source & destination, and if I was writing a tutorial I would have.
  • Heater.Heater. Posts: 21,230
    edited 2012-01-23 10:30
    Eric,
    If you use PAR as a word or byte pointer what happens when the word or byte does not happen to be on a long boudary address? Which I think is most likely to happen.
  • ericballericball Posts: 774
    edited 2012-01-23 10:43
    Heater. wrote: »
    Eric,
    If you use PAR as a word or byte pointer what happens when the word or byte does not happen to be on a long boudary address? Which I think is most likely to happen.
    My point is unless you have some reason to access ROM, then PAR[15] will always be zero (for a long pointer). So why not shift the address so bit 1 is PAR[2], then unshift in the PASM to access the data. As long at the pointer is WORD aligned, you're golden.
  • Heater.Heater. Posts: 21,230
    edited 2012-01-23 12:06
    Sorry, yes, I'm with you now.
    What happens when you move your code to the Prop II with more than 32K RAM?
  • ericballericball Posts: 774
    edited 2012-01-23 12:36
    Heater. wrote: »
    What happens when you move your code to the Prop II with more than 32K RAM?
    My assumption is all PASM (and possibly SPIN) code will need to be tweaked for the Prop II, some more than others.
  • frank freedmanfrank freedman Posts: 1,977
    edited 2012-01-23 18:47
    Harprit wrote: »
    First let me thank every one who has provided me with such tremendous support in this effort. Thank you guys.


    Commenters want me to make the code as fast a possible. Which I am obviously not doing at this time on purpose. I have a very good reason for doing this. The emphasis at this time is to convince the reader that there is nothing intimidating in all this The emphasis is to introduce concepts one at a time as painlessly as possible and not get carried away with concepts either.

    H

    Just in case I may have inadvertently caused some mis-understanding, my statement regarding code which is tight and efficient does not necessarily mean fast as possible. It was meant as clean, concise and maintainable. As fast as possible can many times violate one or all of these concepts.

    Regarding my fourth comment about the ideal place to describe the power of loops (a very basic premise to any programming language), don't have a long stream of in-line code (which will inherently run the fastest of all though gobbling up valuable words of storage). Rather, use reading one single bit to show how the I/O is done, and maybe a second to show how the serial input will be converted into parallel data values. Then build on this concept with the loop to read the whole thing. Present as two simple, short concepts that unlock enormous power in a program.

    As to unlearning, yes, it can be done, but why learn that way? That is like the coach telling the pitcher "Don't give this guy a low and inside pitch cause that's his sweet spot" and then watching the pitcher throw that exact ball. A negative goal is just as powerful as a positive. Also who will straighten out all the hobbiest level learners? In the work force all of the bad habits will be wrung out of a programmer by harsh code reviews with peers and occasional C.L.M.s resulting from poor coding practices causing missed deadlines and un-maintainable code. The hobby level programmer will muddle along for a long time not knowing any better. Teach it right from the beginning or not at all.

    As I stated above, your commenting style is improving. You are doing far less [mov this, that ' move this to that] type of comments and that is good. A comment that says makes sense as shorthand type of comments. Comments in code are not supposed to be detailed explanations. That is the project functional description where you lay out in detail what the overall code is to accomplish, what are the inputs, outputs, and what flow whether in charts, pseudo-code or descriptive prose or generally a combination of these will inform the reader/learner/maintaining engineering team just what was intended and how it was to be implemented. That also in your case will be the purpose of the text in your book. Comments in your code should be landmarks which tie back to the concepts you present in your text.

    One final note, you should put your final code that you will publish up here so that you and your potential readers can gain the benefit of peer review across all levels of experience in this forum


    Frank Freedman

    P.s. I don't really understand the intimidation factor of assembler. It is coding at its most basic level (well short of ones and zeros, ick!). No surprises, absolute and full control. You need to provide more detail in coding as you are not abstracted through say C or Java or even something even more high level. But I really like what I can do with PASM. I would love to get my hands on a good macro ASM such as the NASM or similar. Moving to a higher level of abstraction may help overcome intimidation, add some structures not found native to your flavor of assembler, but you do pay a price in performance for that abstraction. In the case of C, you also gain portability; probably the best reason to grab Prop-GCC or catalinaC and learn to use C.
  • ericballericball Posts: 774
    edited 2012-01-24 10:33
    Just a comment - when I say unlearn, what I'm referring to is correcting an incorrect fact or assumption.

    For example, because SPIN code and data is stored in HUB RAM, all variables are shared (either explicitly or via address pointers). However, PASM code and data is stored in COG RAM, so there is no sharing unless the data is first stored in HUB RAM. Furthermore, in SPIN you can update a variable in a DAT section, but that has no impact on the variable which has already been copied to COG RAM. But if you base your understanding of how variables are shared on SPIN then your PASM code won't work as you expect.

    Another example is in 6502 ASM a subtraction borrow clears the carry flag, but in PASM the carry flag is set.
  • HarpritHarprit Posts: 539
    edited 2012-01-24 11:37
    I have asked Parallax for a conf
    Not heard from them yet
    Will report results
    H
  • kuronekokuroneko Posts: 3,623
    edited 2012-01-24 16:40
    Harprit wrote: »
    I have asked Parallax for a conf
    I'm curious, what do you expect them to tell you which we haven't already answered in posts #575/#576 (1st half)?
  • HarpritHarprit Posts: 539
    edited 2012-01-25 15:17
    @kureneko

    I hope to shorten the feed back cycle from a day or two to a few minutes so I can proceed with my book
    I hope they will be able to refer me to a document that defines how to use the instruction per their guidelines.
    I hope to get a definitive description of their intent for the instruction
  • frank freedmanfrank freedman Posts: 1,977
    edited 2012-01-25 16:17
    Harprit wrote: »
    @kureneko

    I hope to shorten the feed back cycle from a day or two to a few minutes so I can proceed with my book
    I hope they will be able to refer me to a document that defines how to use the instruction per their guidelines.
    I hope to get a definitive description of their intent for the instruction


    @ harprit
    Please do not proceede any further with a book until you fully understand what your subject matter is and can accurately and fully explain to a beginner in such a way as to not confuse, frustrate and drive away a potential propeller user. You are not ready for this task yet as evidenced by errors and attitudes demonstrated in this thread. Go back to square one and examine the most basic concepts one at a time without obfuscating them by trying to bite off way to much at a time. Get PAR understood and cog to hub communications mastered on extremely simple code such as presented very early on by some of the forums journeymen and masters. Then start playing with more than flashing LEDS which are the domain of the beginner anyway. ADCs, servos and steppers, are more fun but introduce perhaps too many more new concepts which further cloud the understanding of the basic concepts on which the beginners will need to build their projects and experience. Your current attempts will likely leave your beginners with a cracked foundation upon which to build.

    You seem to hope for much, but you have far too much work to do on your own before you take the role of master upon yourself in print. As for Parallax, to endorse such a work in light of this thread, I feel would be inappropriate and ill-advised. The thread has provided me with much good advise and examples from the Kuroneko's, Heaters, PotatoHeads, PhiPis, JohnnyMacs, and a whole host of others so there is some redemption to this thread. You don't always seem to accept much of what these highly experienced users have patiently tried to offer to you.

    I am sorry if this view offends you, but this is how I see it. I will continue to read this thread however, because the contributions of the members of this forum have been invaluable to my own understanding. I do hope that the leadership at Parallax will take this thread and evaluate it in light of their existing literature and if a book specific to PASM is warranted will get the leading contributors and users of the Propeller to write or collaborate on writing such a book for the better understanding of the rest of us. Same for a Propeller specific eDocument on Prop-GCC as Parallax is the proponent of that project.


    Frank Freedman
  • HarpritHarprit Posts: 539
    edited 2012-01-25 18:29
    Thank your Frank. I'll keep your good advise in mind. I think you may just have convinced me that I am wasting my time. Maybe I just need to forget about it. My apologies to all who might have been looking forward to my book. Maybe its worth it to take the time for all of you to thank Frank too. He may just be saving you a lot of headaches.
    I personally now know what I need about PASM. Its probably a good time as any to stop this madness on my part.
    H
  • HarpritHarprit Posts: 539
    edited 2012-04-20 09:32
    I'm still working on the book but will not be posting much till I get done.
    Stay tuned. About two months to the finish.
    I will self publish so it will be available immediately upon completion.
    H
  • PublisonPublison Posts: 12,366
    edited 2012-04-20 09:36
    Harprit wrote: »
    I'm still working on the book but will not be posting much till I get done.
    Stay tuned. About two months to the finish.
    I will self publish so it will be available immediately upon completion.
    H

    Welcome back Harprit! Good to know your are still working on the book. It is needed.

    Jim
  • HarpritHarprit Posts: 539
    edited 2012-04-20 11:44
    Thank you Jim
    H
  • Bob Lawrence (VE1RLL)Bob Lawrence (VE1RLL) Posts: 1,720
    edited 2012-04-20 15:56
    @ Harprit


    re:Stay tuned. About two months to the finish.

    Great to hear. I've been waiting. I'll have some extra learning time over the summer, good timing. :cool:

    Bob
  • User NameUser Name Posts: 1,451
    edited 2012-04-20 17:54
    Seems to me that even if the resulting book isn't the most authoritative or comprehensive tome ever - or even if it isn't entirely correct - it will still provide a most important bridge between complete confusion and basic understanding. Once the light bulb of basic understanding switches on, there are many other resources to call on.

    I recall that the first reading of deSilva's little tutorial created far more questions than it provided answers. A week later it had magically transformed itself into a clear and concise friend, and deSilva had suddenly become a genius. Unfortunately that week was full of hair pulling and finger pointing. I have high hopes that your book will prevent that sort of experience.
  • HarpritHarprit Posts: 539
    edited 2012-04-23 12:34
    It is and will be the best that I can do.

    After that the experts will get to say what they think.
    The experts have been unbelievably helpful to my effort but unfortunately its not for them.

    And the beginners will get to say what they think
    What the beginners say will be the definitive call to my mind..

    H
  • HarpritHarprit Posts: 539
    edited 2012-04-23 12:39
    Here is how it begins

    [FONT=Arial, sans-serif]Preface.[/FONT]




    [FONT=Arial, sans-serif]The first question you want answered is of course “Can I learn how to do this?” And the answer is “Yes you can and it is not hard.” That said, you need to understand that this is a new way of doing things and it will take a while before you are good at it. It is not difficult and as you will see, you will be writing simple programs in no time. As time goes on you will be able to write more and more sophisticated programs. If you stick with it, you will get fairly good at it but if you want to be an expert, you will also need some considerable expertise with binary mathematics and a formal course junior college level in assembly language programming might be in order. There is much to be said for self taught programmers but in the age of information, a formal introduction to a subject cannot be treated with casual disregard. [/FONT]


    [FONT=Arial, sans-serif]This book is in landscape format to accommodate the extensive documentation for each line of code on the same line as the code itself! I thought it was important that it be that way.[/FONT]


    [FONT=Arial, sans-serif]This book is for beginning hobbyists, technicians and engineers interested in the use of the propeller chip at a higher level, by using the chip's assembly language capabilities. It introduces you to this language, known as PASM, in a format suitable for beginners. When you are done with the book you will be able to write simple (and maybe intermediate level) programs in PASM. You will not be an expert, but you will not be intimidated by the language either. Since anything that needs to be done quick;y needs to be done in PASM all serious users of the Propeller chip need to have a familiarity with its assembly level language. [/FONT]


    [FONT=Arial, sans-serif]Programming is a “craft skill”. You cannot get good at a craft by reading about it. You have to do it. To get good at it you have to do a lot of it over time. Its like laying bricks, you can watch all the bricklayers you can find forever but till you get your hands on some bricks and mortar, you don't really have a clue about what its all about. So it is with programming![/FONT]
  • Prophead100Prophead100 Posts: 192
    edited 2012-08-29 18:56
    Any updates on the book?
  • HarpritHarprit Posts: 539
    edited 2012-08-30 17:23
    The book is still is very much in the works and getting close to done. I am into the projects now.
    I decided to take a break from the writing (it was getting me burned out) and design and build a state of the art, larger format 3D printer for the hobbyists.
    Its nominal build size is 12 by 12 by 8 inches and it will be of interest to the group interesting in writing the software for a Prop based 3D printer.
    It takes only a 7/16 inch (11 mm) wrench to assemble and dis-assemble the entire printer! Its easy and requires minimal skill.
    Overall dimensions about 18 by 18 by 28 inches. So its a big table top machine.
    Very smooth operation. It has almost 80 ball bearings in it! Everything is on bearings for a very smooth and easy action.
    It is almost done and when it is I will post pictures on the discussion forum for the above software effort.
    Copies of the printer will be available to interested parties without the processor board but with motors (Nema 34) and optical limit switches in place.
    I am hoping to keep the cost to under $1000.00 for a semi assemble kit.
    Semi assembled because otherwise it would be too large to ship inexpensively. It would take a huge box.
    H
Sign In or Register to comment.