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

Propeller Assembly for beginners

12324252729

Comments

  • MJHanaganMJHanagan Posts: 189
    edited 2013-12-02 14:04
    fataldave wrote: »
    I also picked up this book, I was looking for something on PASM and this was the only one I found. I have to agree with red, its current state is that of a draft, many spelling and general errors are distracting at least for me to keep with the flow of the book. There is also a little repetition as it seems things were moved around but the original part not removed. Overall I think it was helpful, I am about half way done with the book. It has a lot of well documented code and examples that are easy to follow.
    __red__ wrote: »
    Honestly, I think it's rough and needs some serious editing before I would consider it of commercial quality. In many cases it feels like the author is repeating things he's seen in this thread and doesn't understand them himself. This may just be a styling issue which copy-editing could address but regardless, it was the impression I was left with.

    Admittedly, I came to the book as someone who became "dangerous" in PASM from these two tutorials: http://gadgetgangster.com/news/45-designer-news/275-propeller-assembly-tutorial.html



    Red

    I brought this book a few months ago as I wanted to lean a bit more about PASM. My immediate need was to increase the measurement speed of an MCP320x ADC beyond the ability of SPIN. This book used this device extensively in its examples. The idea of using the MCP320x device as a leaning tool is a good one since it requires I/O, timing and general passing back and forth of values to the main hub memory. Unfortunately the book does not directly address the details in MCP320x datasheet regarding I/O (minimum and maximum clock speed, minimum sampling capacitor charge time, etc.). There were some missed opportunities to really help the reader understand the intricacies of this device and how PASM can handle them quite nicely. It seems like the author had the right idea of starting out with SPIN to introduce how the MCP320x works. In fact I would have written the first example program with no loops (yup, every painful clock tick and data line I/O on its own line). Then show how you can condense the SPIN code down - perhaps taking two or three iterations to get to something nice and tight. Then transition this same approach with PASM showing how similar the languages are and where PASM differs and how much faster it can run. Condensing PASM to its minimal size seems quite tricky to me as a beginner as it requires much more attention to detail. If the book had taken this approach it might have been more effective in teaching me PASM.

    While I got a few tips from reviewing the code examples, the book itself lacked flow and continuity. I could see glimpses of points trying to be made but it seems too disjointed to be readable to any reasonable extent. It reads like a draft concept of an "Introduction to PASM" rather than an initial publication. A bit verbose in several sections, the illustrations lack clarity as the very thin lines are hard to see, the overall text formatting is poor and the index is awful. This book would have greatly benefited from some editing by a third party (the editing process has value!).

    I have gleaned far more PASM learning from potatohead's and desilva's PASM pdfs than from this book.

    The SPIN manual is a good reference guide for PASM too but it lacks practical examples for each command and virtually no examples of common command snippets. As a beginner I had to spend lots of time looking for examples of how to do basic SPIN coding somewhat efficiently. Seems like well documented PASM examples for the beginner are quite rare. Parallax has a scant set of 19 application notes (and it seems like you have to go to the Parallax Semiconductor site to get them now). I have often wondered why Parallax has not written an "Introduction to SPIN" and an "Introduction to PASM". Especially since they seem to want to promote the Propeller chip to the beginner student.

    I don't think I'm alone in still waiting for a good "Introduction to PASM" tome.
  • potatoheadpotatohead Posts: 10,261
    edited 2013-12-02 14:26
    I'm an experienced Assembly programmer.
    But PASM still eludes me.
    I just haven't found a starting point yet.

    Please tell me about this. I understand something about people who have not had assembly experience, but I really don't understand experienced assembly language programmers having trouble with PASM. What sort of questions are you asking and how do those link to concepts you may or may not associate with PASM?

    If you could enlighten me, and it's not a problem to put it here, I would very much appreciate that discussion. That applies to anyone BTW. Thanks.
  • HarpritHarprit Posts: 539
    edited 2013-12-02 17:40
    I am confident that a much better book could be written for beginners. A much better book.
    Any one who cared to do so could have done so but no one is even threatening to do so even as I type..
    People who know a lot more about PASM than I do could have done it. They did not.
    Parallax has not done so... so far.
    No one has.
    The book did you some good if one, you now know a bit more about PASM than you before started and two if you can now write simple code in PASM
    The answers to both questions are yes (from those buyers who cared to answer the questions for me).
    So many technical books are so full of data sheets copied from the internet files. I chose not to do that.
    I also did not repeat what is already in the Propeller Manual.
    There are about 90 pages of code in the book and each and every line is commented.
    Most of the code on the internet is Greek to beginners. It was to me.

    Comments about flow and style may indeed be relevant but do not address the learning experience directly.
    I asked at least 100 questions on the forum as I wrote the book.
    The answers were sincere but not overly enlightening to my beginner's mind set.
    I had to figure most of it out the hard way. Hopefully my efforts will save beginners some headaches.
    PLEASE WRITE A BETTER BOOK.
    Light a candle, don't just curse the darkness.

    Harprit
  • fataldavefataldave Posts: 61
    edited 2013-12-02 18:04
    Harprit wrote: »
    I am confident that a much better book could be written for beginners. A much better book.
    Any one who cared to do so could have done so but no one is even threatening to do so even as I type..
    People who know a lot more about PASM than I do could have done it. They did not.
    Parallax has not done so... so far.
    No one has.
    The book did you some good if one, you now know a bit more about PASM than you before started and two if you can now write simple code in PASM
    The answers to both questions are yes (from those buyers who cared to answer the questions for me).
    So many technical books are so full of data sheets copied from the internet files. I chose not to do that.
    I also did not repeat what is already in the Propeller Manual.
    There are about 90 pages of code in the book and each and every line is commented.
    Most of the code on the internet is Greek to beginners. It was to me.

    Comments about flow and style may indeed be relevant but do not address the learning experience directly.
    I asked at least 100 questions on the forum as I wrote the book.
    The answers were sincere but not overly enlightening to my beginner's mind set.
    I had to figure most of it out the hard way. Hopefully my efforts will save beginners some headaches.
    PLEASE WRITE A BETTER BOOK.
    Light a candle, don't just curse the darkness.

    Harprit

    I hope you didn't take my comments negatively. As I said before, overall it is a helpful book. So far (Not yet finished) I have picked up many things I didn't know. I was just saying it needs a bit of review to make it flow better and remove some errors, but this was not a put down of the book but more a suggestion for the next revision. Also as you just noted, as well did I, that this book fills a void as it was the only one I found that covered PASM.

    Thanks for your work on this book.
  • potatoheadpotatohead Posts: 10,261
    edited 2013-12-02 20:47
    @Harpit you said:
    PLEASE WRITE A BETTER BOOK.
    Light a candle, don't just curse the darkness.

    Yes. Needs to happen. Maybe someday. You did work hard and you did write a book. I've refrained from any commenting on it, because you made your contribution to fill a vacuum, and you did it with your best intent too. And it's going to benefit some people. :)
  • User NameUser Name Posts: 1,451
    edited 2013-12-03 08:45
    cavelamb wrote: »
    I'm an experienced Assembly programmer.
    But PASM still eludes me.
    I just haven't found a starting point yet.

    If you're an experienced Assembly Programmer, surely you could follow de Silva despite its quirkiness.
  • RaymanRayman Posts: 14,761
    edited 2013-12-03 11:12
    I think I mostly learned from de Silva's guide... I think it's great that there's a new beginner's book though, even if it isn't perfect.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2013-12-05 22:02
    MJHanagan wrote: »
    While I got a few tips from reviewing the code examples, the book itself lacked flow and continuity. I could see glimpses of points trying to be made but it seems
    too disjointed to be readable to any reasonable extent. It reads like a draft concept of an "Introduction to PASM" rather than an initial publication. A bit verbose in
    several sections, the illustrations lack clarity as the very thin lines are hard to see, the overall text formatting is poor and the index is awful. This book would have
    greatly benefited from some editing by a third party (the editing process has value!).

    I just read the comments before I was planing on purchasing the book, but your comments sound as though you could
    be talking about Harprit's book on SPIN.
    MJHanagan wrote: »
    I have gleaned far more PASM learning from potatohead's and desilva's PASM pdfs than from this book.

    Unfortunately Potatohead's and Desilva's PASM pdfs didn't help me, and that is why I was interested in Harprit's
    book on PASM
    .

    I have the Parallax book by Gunther Daubach for Programming the SX, Several books on programming the PIC, assembly
    programming the 486, by Irvine and other mpu's. They have helped me develop some basic ideas, but all I own is Parallax
    products, and I really have no interest in any other manufactures products.

    I realize writing a book on such a specialized subject like this is not a money maker for the author, and Parallax can't
    pay someone for all the time it takes to write a proper book. Why can't Parallax (with some help) write a downloadable
    PDF similar to the Basic Stamp books, that were free to download, and with that old style Parallax experience?
    Keep it simple, and use the IC's Parallax sells as examples people can incorporate into their own projects, instead of
    projects we will never build.

    I also have many of Jon Williams Nuts and Volts articles, but to many of them deal with projects I have no interest in,
    and for me, that is similar to reading a book about programming a PIC in assembly without the interest or intention to
    ever do so.

    fataldave wrote: »
    I hope you didn't take my comments negatively.

    Sorry, but it was kinda difficult to read it any other way. Is there any positive features you can point out?


    Thanks

    Bill M.

    ps; maybe create a wiki page that anyone can contribute too.
  • fataldavefataldave Posts: 61
    edited 2013-12-06 06:39
    Sorry, but it was kinda difficult to read it any other way. Is there any positive features you can point out?

    In the post I was referring to, I pointed out improvements and what I liked:
    fataldave wrote: »
    Overall I think it was helpful, I am about half way done with the book. It has a lot of well documented code and examples that are easy to follow.

    The book has a LOT of well documented easy to follow code, many of the examples and OBEX stuff I have found have complex parts that have a general statement of what they intend to do rather than what every line is doing like in the book. The content of the book is good, and was informative.
  • HarpritHarprit Posts: 539
    edited 2013-12-07 20:19
    Thank you Dave, you have been very kind.

    I wish a lot more of the buyers would post here instead of telling me about it.
    You can learn a lot from the book if you are a beginner. 80 pages of pure PASM code. Every line documented and easy to follow. I send you the file so you don't have to retype a thing.
    Unfortunately the fingers of naysayers are faster to the keys than those that were helped.

    I am pretty sure no one else will write a book. I have two books on PICs that with their two e-versions have been in the top 50 PIC books every week for well over three years. Often number 1 is a book by me. That is 4 out of the top 50!!!! I think its a record.
    My royalty check from McGraw last quarter $21.00.

    Here is a review of my books written as the reviewer reviewed another book NOT written by me.

    Two of the best books on PIC controllers are written by Mr. Harprit Singh Sandhu. They both contain a lot of circuit examples , and programming examples to work with the circuits. The books are based on the Melabs Lab-X1 demo board, but you do not need the board to get a feel for the controllers, or the programming. Mr. Sandhu steps through his programs with great detail, and makes them very easy to follow with excellent programming commenting.
    The programming used in his books is based on MeLabs Pic Basic Pro. Pic Basic Pro comes in various versions, so depending on your needs, the cost can vary between free, $49 fr a student, $120 for Silver, and $250 for a Gold license. I bought the silver license, and have been very happy with it.
    I have two of Mr. Sandhu's books, and a coupe of others that explain PIC functions, and circuit examples with Basic org ramming examples. The some of the best advice Mr. Sandhu will give you is about the data sheets, and various PIC's. That is to pick a PIC to work with, and study it so you will know it well. The programming will be much easier once you understand the functions of the PIC you choose to work with However, both of his books are based on the Lab-X1, and the 16F877a PIC. This PIC is a 40 pin work horse of a PIC, but once you can work with this one PIC, you will be able to easily work with most others. The programming from one PIC can be transferred to many others with very little rework, or effort.
    I hope you, as a reader, feel I have helped you get on the fast track to learning about PIC programming. It is a lot of fun, easy, and well worth the time you will put into it.

    My spin and PASM books are in the same vein. As regards the gripe about my repeating stuff (which is minimal). This is a reference text you will use hundreds of times. You should not have to spend time finding lines of specific code in the middle of hard to understand machine language. Repeating it where needed in the discussion avoids this.

    And the book is not full of data sheets copied from the internet or information that is already in the Propeller manual. Not one line.

    H
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2013-12-26 10:01
    I bought the book, and it is helping me learn PASM.

    Thanks


    Bill M.
  • HarpritHarprit Posts: 539
    edited 2013-12-27 13:03
    Capt Q.

    Thanks for your kind comment.

    I read your unedited post very late last night and note that you have deleted some or your questions by this afternoon.
    I do not remember your exact wording now but here goes. Maybe this will help.

    I found that I could use 100K pots on the 3208 without problems. The usual recommendation is 5K pots. Since the pots are all placed across the power supply, they eat up the amps pretty fast and soon the prop starts to reset and readings become unreliable for low and high values of the pot reading (at 12 bits). Specially important if you want to or need to place 8 units across the power supply.

    The slow down on the 3208 at lower voltages can be compensated for by slowing down the Propeller if that is necessary. My experience was that the chip was fast enough to keep up with the Prop. In these cases it is best to run a test to satisfy yourself for the conditions that you have on your board are not creating a problem.

    I dwell on the 3208 in the book so that I can stick with one chip that has almost universal appeal if you are interested in real time inputs and in reading all sorts of sensors. If you learn to use the 3208, the rest will be easier.

    Call me if you want to discuss further 217 269 8737 any time.

    H
  • Heater.Heater. Posts: 21,230
    edited 2013-12-27 22:04
    "$49 for a student, $120 for Silver, and $250 for a Gold license"

    Ah! the good old days.


  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2014-01-01 15:16
    I decided to post these questions here rather than call because it may help someone else.


    (1) I am having problems understanding some of the pasm code from "064 PASM_Book_ReadPot.spin."
    Primarily the Global Label "read_bit." My problem is recognizing how the data is transferred from the
    data out pin #27 to the PAR register.

    Today I realized the Z-flag might be treated as a global variable that can be changed by any instruction
    line after it has been set?

    For several days now, I could not see the relationship between "temp" and "dat_red." Note: If you look
    at my version of the code, I tried to use the Basic Stamp and SXB code conventions, and changed some
    of the names to be more meaningful to me. Such as: "longTmp" instead of "temp," and "readData"
    instead of "dat_red."

    I was unable to use the Propeller Manual to solve this problem by myself. I have used the MCP3208
    data sheet to get a more in depth understanding of the adc chip.

    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 ready for next bit
          if_nz add    Dat_red,  #1     'if value is positive add 1 to data register
                call   #Tog_Clk         'toggle clock to get next bit ready in Dout
                sub    count,    #1 wz  'decrement "bits read" counter. Set Z flag
          if_nz jmp    #read_bit        'go up and do it again if counter not yet 0
                mov    mem,      par    'get address of par into mem
                wrlong dat_red,   mem   'write it in HUB to share it as P.Val
                call   #Chip_Sel_Hi     'Put chip to sleep by de-selecting it
                jmp    #generate        'go back to do it all again
    


    This is my version of the code:
    Read_Bit    mov     longTmp,      ina                 ' Read all input pin status, and store in longTmp
                andn    longTmp,      mask26  wz          ' Mask off all pins except Dout pin, and set Z flag
    
    '' If the WZ effect is specified, the Z flag is set (1) if the resulting Value equals zero. 
    '' If the WC effect is specified, the C flag is set equal to Value’s original bit 31. The 
    '' result is written to Value unless the NR effect is specified.
    
    '' SHL (Shift Left) shifts Value left by Bits places and sets the new LSBs to 0.
    
    '' ??? Is the Zero Flag treated as a global variable that can be changed by any
    '' ??? instruction after it is set?
    
    '' ??? Is the a method that is more transparent to demonstrate how the Data out 
    '' ??? pin (longTmp) is recorded on each index itteration?
    
    
                                                    '  %00000000_00000000_00000000_00000000
                shl       readData,     #1          '  %00000000_00000000_00000000_0000000    
                                                    
        if_nz   add       readData,     #1          ' if Z clear,  add 1 to readData.
                call      #Toggle_Clk
                sub       index,        #1    wz  
        if_nz   jmp       #Read_Bit
                mov       parMem,       par
                wrlong    readData,     parMem
                call      #CS_Hi
                jmp       #Generate
    


    (2) I am having problems finding a truth table for the "andn" instruction. The Propeller
    manual describes it as: "ANDN (bitwise AND NOT) performs a bitwise AND of the inverted
    value (bitwise NOT) of Value2 into that of Value1"


    '---------- Subroutines ----------------------------------------------------------      
    Clk_Hi          or      outa,     ClkBit        ' Pin #27
    
    '' Bitwise OR: 
    '' The result in each position is 1 if the first bit is 1 or the 
    '' second bit is 1 or both bits are 1; otherwise, the result is 0. 
    
    Clk_Bit_ret     ret                         ' Used to mark the end of the sub.
    '----------------------------------------
    Clk_Low         andn    outa,     ClkBit
    Clk_Low_ret     ret
    

    I have looked at Microsoft, Wikipedia and other programming websites and they don't
    seem to use the same terminology for some bitwise operators.

    Can someone please help me understand ANDN? and does the ANDN and the OR
    effect the entire 32 bit long?



    Harprit recommends to use the Propeller Manual and the MCP3208 data sheet
    as additional references in addition to the book. Despite the fact the books unfinished
    appearance, the book has worked well for me because it isn't perfect. It kinda forced
    me to study, and that works for my personality. It is difficult for me to accept something
    as real, genuine, or a fact, without my own investigation into what is presented to me.

    Despite the well documented code, I ended adding my own comments, some directly
    from the mcp3208 data sheet and propeller manual. I also documented the step by step
    process of the mcp3208.

    The largest difference to me, is the code is relatively easy to read, and therefore easy
    for me to follow and develop a deeper understanding of the basics. On the other hand,
    trying to read polished code in some other books has made it difficult for me to continue
    reading those books.

    For example: this is my take on Harprit's code:
    CON
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
    ' -------------------------------------------------------------------------------
    VAR
    
      long PVal
    ' -----------------------------------------------------------------------------------
    OBJ
    
      fds : "FullDuplexSerial"
    ' ------------------------------------------------------------------------------------
    PUB
    
      fds.start(31,30,0,115200)
      cognew(@generate, @PVal)
      repeat
        fds.bin(P_Val, 12)
        fds.tx($d)
        fds.dec(P_Val)
        fds.tx("  ")
        fds.tx($1)
        waitcnt(clkfreq / 60 + cnt)
    
    ' -----------------------------------------------------------------------------------
    DAT
    
    '' DATA IN is always read from the device 
    '' on the RISING EDGE of the clock.
    
    '' DATA OUT is always read from the device 
    '' on the FALLING EDGE of the clock.
    
    
                      org   0                ' Starting point.
    Generate    mov   dira,   SetDira        ' Set Direction.
    
    '' Initiating communication with MCP3208 
    '' is done by bringing the CS line low. 
    
    '' If the device was powered up with the 
    '' CS pin low, it must be brought high 
    '' and back low to initiate communication.
    
    
    '' The first clock received with CS low 
    '' and DIN high will constitute a START 
    '' BIT.
                  
                  call  #CS_Low              ' Chip select, pull low.
                  call  #Clk_Low             ' In order to start, Clk must be set low.
                  call  #Din_Hi              ' In order to start, Data In must be set high.
                  call  #Toggle_Clk          ' In order for the mcp3208 to read data from the Propeller
                                             ' the, we need to toggle the clock to high and back to configure Start Bit.
                                             ' The first Toggle_clk recieved with CS_low & Din_hi will constitute
                                             ' the first START_BIT. 
    '' START_BIT Declared
                                         
                call  #Din_Hi                ' Din_hi sets the single or differential mode of the data configuration,   
                                             ' when set Hi the MCP3208 is set to read from 8 single ended inputs.
                call  #Toggle_clk            ' Toggle clk from low to high and back to low to configure Data In.
    
    '' SINGLE_END Declared
    
                call  #Din_low               ' Din_low sets data configuration bit D2
                                             ' CH 0 input configuration on D2-D0 is %000
                call  #Toggle_Clk            ' Toggle clk from low to high and back to low to configure Data In.
                call  #Din_Low               ' Din_low sets data configuration bit D1
                call  #Toggle_Clk            ' Toggle clk from low to high and back to low to configure Data In.
                call  #Din_Low               ' Din_low sets data configuration bit D0
                call  #Toggle_Clk            ' Toggle clk from low to high and back to low to configure Data In.
    
    '' FOURTH_RISING_CLOCK
    
    '' SAMPLE_PERIOD_BEGINS
    
    '' The MCP3208 will begin to sample the analog
    '' input on the fourth rising edge of the clock 
    '' after the start bit has been received.
    
    '' Once the D0 bit is input, one more clock is required to
    '' complete the sample and hold period (DIN is a “don’t
    '' care” for this clock).
    
    '' The sample period will end on the falling 
    '' edge of the fifth clock following the start
    '' bit.          
            
                  call  #Toggle_Clk           ' Sample period ends            
     
    
    '' On the falling edge of the next clock, the MCP3208 will 
    '' output a low null bit. 
    
    '' The MCP3208 must shift from recieving instruction as the clock 
    '' rises, to supplying data on the falling edge of the clock. In 
    '' order to do so, it takes 1 1/2 clock cycles to make the change.
    
                  call  #Toggle_Clk               ' Triggers the first output as the Null Bit.
                  mov   readData,   #0            ' No real data from the MCP3208, so clear the file location. Mainly applies to the 2nd data
                                                  ' read, and every data read afterwards. 
                  mov   index,      #12           ' Creates an index that counts down after each Clock Cycle. (it was count)
    
                
    '' The next 12 clocks will output the result of the conversion 
    '' with MSB first. 
    
    '' Data is always output from the device on the falling edge 
    '' of the clock. 
    
    '' If all 12 data bits have been transmitted and the device 
    '' continues to receive clocks while the CS is held low, the 
    '' device will output the conversion result LSB first. 
    
    '' If more clocks are provided to the MCP3208
    '' while CS is still low (after the LSB first data has been
    '' transmitted), the device will clock out zeros indefinitely.
    
                  
    Read_Bit    mov     longTmp,      ina                 ' Read all input pin status, and store in longTmp
                andn    longTmp,      mask26  wz          ' Mask off all pins except Dout pin, and set Z flag
    
    '' If the WZ effect is specified, the Z flag is set (1) if the resulting Value equals zero. 
    '' If the WC effect is specified, the C flag is set equal to Value’s original bit 31. The 
    '' result is written to Value unless the NR effect is specified.
    
    '' SHL (Shift Left) shifts Value left by Bits places and sets the new LSBs to 0.
    
    '' ??? Is the Zero Flag treated as a global variable that can be changed by any
    '' ??? instruction after it is set?
    
    '' ??? Is the a method that is more transparent to demonstrate how the Data out 
    '' ??? pin (longTmp) is recorded on each index itteration?
    
    
                                                    '  %00000000_00000000_00000000_00000000
                shl       readData,     #1          '  %00000000_00000000_00000000_0000000    
                                                    
        if_nz   add       readData,     #1          ' if Z clear,  add 1 to readData.
                call      #Toggle_Clk
                sub       index,        #1    wz  
        if_nz   jmp       #Read_Bit
                mov       parMem,       par
                wrlong    readData,     parMem
                call      #CS_Hi
                jmp       #Generate
    
    
    '---------- Subroutines ----------------------------------------------------------      
    Clk_Hi          or      outa,     ClkBit        ' Pin #27
    
    '' 
    Bitwise OR: 
    '' The result in each position is 1 if the first bit is 1 or the 
    '' second bit is 1 or both bits are 1; otherwise, the result is 0. 
    
    Clk_Bit_ret     ret                         ' Used to mark the end of the sub.
    '----------------------------------------
    Clk_Low         andn    outa,     ClkBit
    Clk_Low_ret     ret
    '-----------------------------------------
    Toggle_Clk      call    #Clk_Hi
                    call    #Clk_Low
    Toggle_Clk_ret  ret
    '-------------------------------------------
    Din_Hi          or      outa,     DinBit
    Din_Hi_ret      ret
    '------------------------------------------
    Din_Low         andn    outa,     DinBit
    Din_Low_ret     ret
    '------------------------------------------
    CS_Hi           or      outa,     CSBit
    CS_Hi_ret       ret
    '---------------------------------------------
    CS_Low          andn    outa,     CSBit
    CS_Low_ret      ret
    '--------------------------------------------
    Read_Next_Bit   mov     longTmp,    ina
                    or      longTmp,    mask26
    Read_Next_Bit_ret     ret
      
    
    ' ---------- Constants -------------------------------------------------------------
    
    
      SetDira    long   %00001011_11000000_00001111_11111111        'Set dira register
      CSBit      long   %00000001_00000000_00000000_00000000        'Chip select bit     24
      DinBit     long   %00000010_00000000_00000000_00000000        'Data in bit         25
      DoutBit    long   %00000100_00000000_00000000_00000000        'Data out bit        26
      ClkBit     long   %00001000_00000000_00000000_00000000        'Clock bit           27
      Mask26     long   %11111011_11111111_11111111_11111111        'Mask forDout bit only
      Pin23      long   %00000000_10000000_00000000_00000000        'osc line
      Pin22      long   %00000000_01000000_00000000_00000000        'Speaker line
    
    
    ' --------- Variables ------------------------------------------------------------
    
      longTmp     res   1
      index       res   1
      readData    res   1
      parMem      res   1
    
    ' ------------- End of Program ----------------------------------------------------------
    
      Fit
    
    ' -------------------- Definitions ----------------------------------------------------------------
    
    ' CALL  pg. 268
    


    And this is Harprit's original code:
    {{-------------------------------------------------------------------------------
    PASM_Book_ReadPot.SPIN
    Function of program
    Makes an electronic Metronome.
    
    Notes:  Program reads a potentiometer
    See details in book
    
    Program         PASM_Book_ReadPot.SPIN
    Book            PASM for beginners, Propeller 102
    Section         Outputs
    Programmer      Harprit Sandhu   
    Date            Jan 10 2013
    
    Revisions:      Report errors to harprit.sandhu@gmail.com
      
    --------------------------------------------------------------------------------}}
    CON
      _clkmode = xtal1 + pll16x   'set clock
      _xinfreq = 5_000_000        'crystal freq
    
    VAR
      long P_Val                  'declare variable
    
    OBJ 
      fds : "FullDuplexSerial"    'for display to PST
    
    PUB Main  
    fds.start(31,30,0,115200)     'start console at 115200 for debug output
      cognew(@generate, @P_Val)   'start new Cog at "generate" and read variable into P_Val in PASM
      repeat                      'loop
        fds.bin(P_val,12)         'print value to the PST in binary 
        fds.tx($d)                'new line 
        fds.dec(P_val)            'print value as decimal 
        fds.tx(" ")               'space       
        fds.tx($1)                'home to 0,0
        waitcnt(clkfreq/60+cnt)   'flicker free wait
    
    DAT         org    0                 'sets the starting point in Cog
    generate    mov    dira,   set_dira  'sets direction of the prop pins
                call   #chip_sel_lo      'selects chip by pulling line low 
                call   #Clk_lo           'START. Clock needs to be low to load data
                call   #Din_hi           'must start with Din high to set up 3208
                call   #Tog_clk          'clk hi-lo to read data
                call   #Din_Hi           'SINGLE DIFF mode, will be made Low to load
                call   #Tog_Clk          'toggle clock line hi low to read data                 
                call   #Din_Lo  'D2 Low to load input line sel sequence 000 for line 0
                call   #Tog_Clk 'toggle clock line hi then low to read in the data
                call   #Din_Lo  'D1 Low to load input line sel sequence 000 for line 0
                call   #Tog_Clk 'toggle clock line hi then low to read in the data 
                call   #Din_Lo  'D0 Low to load input line sel sequence 000 for line 0
                call   #Tog_Clk      'toggle clock line hi low to read in the data                 
                call   #Din_Lo       'blank bit needs a clock cycle, next
                call   #Tog_Clk      'toggle clock line hi then low to read the data
                                     'next toggle is for the null bit, nothing read
                call   #Tog_Clk      'toggle clock line hi then low to read the data
                mov    dat_red,  #0        'Clear register we will read data into
                mov    count,    #12       '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 ready for next bit
          if_nz add    Dat_red,  #1     'if value is positive add 1 to data register
                call   #Tog_Clk         'toggle clock to get next bit ready in Dout
                sub    count,    #1 wz  'decrement "bits read" counter. Set Z flag
          if_nz jmp    #read_bit        'go up and do it again if counter not yet 0
                mov    mem,      par    'get address of par into mem
                wrlong dat_red,   mem   'write it in HUB to share it as P.Val
                call   #Chip_Sel_Hi     'Put chip to sleep by de-selecting it
                jmp    #generate        'go back to do it all again
     
    'Subroutines
    Clk_Hi        or      outa,   clk_bit  'OR it with the Clock Bit to make high
    Clk_Hi_ret            ret              'return from this subroutine 
    
    Clk_Lo        andn    outa ,   clk_bit 'ANDN it with the Clock Bi to make low
    Clk_Lo_ret            ret              'return from this subroutine
    
    Tog_Clk       call    #Clk_hi          'make clock bit high
                  call    #clk_lo          'make clock bit low
    Tog_Clk_ret           ret              'return from this subroutine
    
    Din_Hi        or      outa ,   din_Bit 'Makes the Din high
    Din_Hi_ret            ret              'return from this subroutine
    
    Din_Lo        andn    outa ,   din_Bit 'makes Din low
    Din_Lo_ret            ret              'return from this subroutine
    
    Chip_Sel_Hi   or      outa ,   chs_Bit 'Makes Chip select high
    Chip_Sel_Hi_ret       ret              'return from this subroutine
    
    Chip_Sel_Lo   andn    outa,   chs_Bit  'makes chip select low
    Chip_Sel_Lo_ret       ret              'return from this subroutine
    
    Read_Next_Bit mov     temp,  ina       'Get the INA register
                  or      temp,  mask26    'mask all but Din bit
    Read_Next_Bit_ret     ret              'return from this subroutine
    '======================
    'Constants. This is similar to the CON block in SPIN but these are not constants
    'because they can be changed.  These are initial values.
    Set_dira   long   %00001011_11000000_00001111_11111111   '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 forDout bit only
    Pin_23     long   %00000000_10000000_00000000_00000000   'osc line
    Pin_22     long   %00000000_01000000_00000000_00000000   'Speaker line
    '============================
    'Variables. This section is similar to the VAR block in SPIN. 
    'These are blank variable space designators
    temp        res    1    'temporary storage variable, misc
    count       res    1    'read bit counter
    Dat_Red     res    1    'data being read
    mem         res    1    'par location
    Fit
    



    A big thanks to Parallax & Jazzed for the Simple IDE. It has been very helpful for
    working on the PASM code!


    Bill M.
  • potatoheadpotatohead Posts: 10,261
    edited 2014-01-01 15:50
    I always had trouble with value2, value1 being mixed in with source and destination. Value 1 = destination, value 2 = source.

    ANDN requires you derive the truth table from the core two that describe the operation of the instruction:

    For each bit, NOT does:

    0 = 1
    1 = 0

    This is just a simple invert the bits function.

    For each bit, AND does:

    1 and 1 = 1
    0 and 1 = 0
    1 and 0 = 0
    0 and 0 = 0

    This is a simple, set the bit only when both argument bits are one function.

    For each bit, combining the two looks like this:
    Value 1 AND (NOT value 2)
    
    1 AND (NOT 1) = 1 AND 0 = 0
    1 AND (NOT 0) = 1 AND 1 = 1
    0 AND (NOT 1) = 0 AND 0 = 0
    0 AND (NOT 0) = 0 AND 1 = 0
    

    The operators work on all the bits. When we do something like AND destination, source, all of the bits in source get operated on in tandem with the bits in destination with the result written to destination.

    ANDN 0111_1000, 1011_0100 =

    First let's NOT the source, applying the truth table above to each bit: (invert them)

    0100_1011

    Then we do the AND:

    0100_1000
    0111_1000
    0100_1000

    One easy way to remember what OR, AND, NOT, XOR do is to think of them like this:

    OR is useful when you want to make sure a bit is 1 no matter what. It's truth table is:

    0 OR 0 = 0
    1 OR 0 = 1
    0 OR 1 = 1
    1 OR 1 = 1

    The 1's in your mask are active and will do something to the other value. The 0's are inactive and do nothing.

    AND is useful when you want to make sure a bit is 0 no matter what. It's truth table is:

    0 AND 0 = 0
    1 AND 0 = 0
    0 AND 1 = 0
    1 AND 1 = 1

    In this case, the 0's are active and will do something to the other value. The 1's are inactive and do nothing.

    NOT is useful when you want to invert a bit. It's truth table is:

    NOT 0 = 1
    NOT 1 = 0

    And XOR is useful when you want to toggle a bit. It's truth table is:

    0 XOR 0 = 0
    1 XOR 0 = 1
    0 XOR 1 = 1
    1 XOR 1 = 0

    In your mask, the 1's will toggle bits in the other value, the 0's won't.

    And now let's talk about masks a little bit.

    When you encounter multiple operations, you solve in the order they happen, which can take a bit of thinking when the instruction wording and argument placement isn't intuitive as ANDN sort of is.

    Now, the power of these things comes with the use of masks. A mask is a pattern that can control which bits are impacted in a long. For this post, I'm going to use words, just because it's shorter, but masks work the same way no matter what your data size is.

    Say we have this word:

    1100_0011_0001_1010

    and we want to make sure bits 3, 4, 6, 7, and 13 are set to 1.

    The mask looks like this:

    0010_0000_1101_1000

    Apply the OR function thus:

    1100_0011_0001_1010
    0010_0000_1101_1000
    1110_0011_1101_1010

    Here is that same mask applied using ANDN:

    1100_0011_0001_1010 (Original)
    0011_1100_1110_0101 (After NOT)
    0010_0000_1101_1000 (now AND with the NOT result above, not the original)
    0010_0000_1100_0000

    Looks to me like it places a 1 in the destination ONLY when there are 1's unique to the destination value. It's truth table is then a combination of the above:

    1 ANDN 1 = 0
    0 ANDN 1 = 0
    1 ANDN 0 = 1
    0 ANDN 0 = 0

    Hope this helps!
  • HarpritHarprit Posts: 539
    edited 2014-01-01 15:55
    This a lot of stuff for me to take in in one gulp!
    I will get back to you in a day or two with some answers and/or comments
    H
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-01-01 17:15
    I'm not surprised that you find that code confusing; Harprit is using an inverse mask to check an I/O pin... why???

    Okay, suppose the input register is: 11001100_11110000_00001111_00110011
    That register is ANDN'd with......... : 11111011_11111111_11111111_11111111 <- any bit with a 1 in it is cleared to zero, and bits with 0 are unchanged
    The result of that instruction is...... : 00000100_00000000_00000000_00000000
    There is still one bit set so the Z flag is clear.
    A one is added to Dat_red by first shifting Dat_red left one, and adding one to the low-bit if the Z flag is clear

    A much simpler method is to take the input register: 11001100_11110000_00001111_00110011
    Use an AND instruction to isolate the bit............... : 00000100_00000000_00000000_00000000 <- any bit with a 0 is cleared to zero, bits with 1 are unchanged
    Which also gives the result.................................. : 00000100_00000000_00000000_00000000

    And instead of using the Z flag, use the C flag which is set if the result has an odd number of bits set.
    Using the C flag makes updating the Dat_red register easier since you can then use a RCL instruction.

    This
    read_bit    mov    temp,    ina       
                andn   temp,    mask26 wz  
                shl    Dat_red,  #1    
          if_nz add    Dat_red,  #1
    
    or this
    read_bit    mov    temp,    ina
                and    temp,    mask26 wc   'where mask26 = |<26
                rcl    Dat_red,  #1
    
    But even that is needlessly complicated unless there's some reason to have a copy of ina.
    Consider that the TEST instruction acts just like a AND instruction, only affecting flags and not a result
    read_bit    test   mask26,  ina    wc
                rcl    Dat_red, #1
    

    Here's my simplified version of the entire read_bit routine:
    read_bit
            mov     loop_counter, #12            ' Receive 12 bits from the MCP3208                                                     
            mov     Dat_red,      #0             ' Clear the Dat_red register                                                           
    :loop                                                                                                                               
            test    mask26,       ina      wc    ' Set the C flag if input 26 is high, where mask26 is |<26                             
            rcl     Dat_red,      #1             ' Rotate C into the low-bit of Dat_red                                                 
            or      outa,         clk_bit        ' Output a high on the clock                                                           
            andn    outa,         clk_bit        ' Output a low on the clock ... why were these in nested subroutines???                
            djnz    loop_counter, #:loop         ' Repeat 12 times                                                                      
            wrlong  dat_red,      par            ' Store the result in par                                                              
            or      outa,         chs_Bit        ' Make Chip select high ... it's silly to create subroutines for a single instruction
            jmp     #generate
    
  • frank freedmanfrank freedman Posts: 1,983
    edited 2014-01-02 00:07
    I could be off on this one, but you may want to add a couple of cycles to the loop to account for the clocks between the end of channel select and the start of data to account for an indeterminant bit and the null bit prior to the actual 12 bit value. On the MC3201, this is 3 cycles for a 15 clock count, and looks like 14 clocks for the MC3208 but I have not used the multi-channel chips and have not fired up the lab in months......... Oh, also, mask the results for however many bits you want to use of the whole value. (Idea grabbed from one of jonnymac's objects)
  • HarpritHarprit Posts: 539
    edited 2014-01-02 08:55
    Please, please, please. This book is for beginners, beginners, beginners. Absolute beginners.
    So.... Comments as to not using sophisticated or rigidly required techniques may not really be applicable in this frame.
    Example I use the ANDN instruction extensively to read a bit because it eliminates the need to learn a new command in the middle of what is already pretty confusing code.
    The learning process has to be as "simple and stupid as possible" if it is going to work for a complicated system. I tried to keep it simple. Too simple for some.

    The general complaint is something like "I learned a bit from this book but not enough!" Well...... it is now your job to take it to the next level.
    On my not going into the intricacies of the 3208... That is not for beginners. The thing is complicated enough as it is.
    I use two and three line subroutines so that the main code flows more easily. This is one of those necessary simplifications.

    The constant statements that published code is impossible to read should not be taken lightly. It is a real problem. As a part of this I looked at Chip's OBEX for the 3208 for comparison and edification.
    It is very elegant, very compact and VERY impressive. I was very much taken by the power of the language as used by an expert.
    It is not heavily commented. I DID NOT FULLY COMPREHEND ONE SINGLE LINE.

    Bill M.
    The data moves from the 3208 to the register we are reading into, a bit at a time
    For each bit we test the z flag to see if it is 0 or 1.
    In either case we move the register we are reading into one bit at a time as we read the data in
    If the z flag was 0, that's it. We are done.
    If it was not 0 we add 1 to the register we are reading into.
    The data is never actually read directly into anything. The z flag determines if we are going to add a 0 or a 1

    The z flag is set as set or cleared after the instruction in which it was specified is executed.
    It can be tested after that if nothing else disturbs it. It does not have to be done immediately.

    Your other commentary is pretty much self explanatory as are the comments by others.

    Thanks for your kind comments
    I admire the effort you are putting into learning PASM. I wish you every success.
    And you may still want to talk to me!

    H
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-01-02 13:56
    The book might be for beginners, beginners, beginners, and absolute beginners, but this thread is about Propeller Assembly for beginners.

    There are a total of 78 PASM instructions, many of these are variants of other instructions, and many others are strongly similar.

    If you can understand ANDN, you can understand AND, TEST, and TESTN.
    If you understand SHL, you should be able to understand SHR, ROL, ROR, RCL, and RCR.
    If you understand SUB #1 wz / if_z JMP, you absolutely should be able to understand DJNZ.
    There is nothing sophisticated about any of those.

    Out of those 78 instructions, there are just over a dozen dissimilar ones that I use regularly. I don't think that's beyond the ability of a beginner to learn. Those instructions are certainly easier to understand than the inner workings of a chip like the MCP3208.

    You mentioned Chip Gracey's MCP3208 object, and I agree that it is a very elegant object and not something I'd expect a complete beginner to to be able to write. It should not be too difficult to understand however. I used it as the basis for my own driver:
    {{
      This sample routine is based on code from Chip Gracey's MCP3208 12-bit/8-channel ADC Driver v1.0
      The data-out and data-in pins are tied together and are operated on by D_mask
      A single register, t1, is used for sending the configuration bits and also for receiving the data bits.  Data is sent from the upper bits and read into the lower bits
      D_mask is initially set to an output in order to transmit the configuration bits, and then changed to an input to receive the data bits
    
           __
           CS    &#61574;&#61574;&#61574;&#61574;&#61574;&#61574;&#61573;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61570;&#61574;&#61574;&#61574;&#61573;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;
           
           CLK   &#61579;&#61579;&#61577;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574; 
                     1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  1   2   3   4   5   6   7   8   9 
                                      
           Din   &#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61578;&#61574;&#61574;&#61574;&#61575;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61578;&#61574;&#61574;&#61574;&#61575;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;
                       &#61600;   &#61600;   &#61600;   &#61600;   &#61600;                                                               &#61600;   &#61600;   &#61600;   &#61600;   &#61600;  
                       &#9474;   &#9474;   A2  A1  A0                                                              &#9474;   &#9474;   A2  A1  A0 
                       &#9474;   SGL/Diff                                                                    &#9474;   SGL/Diff       
                       Start                                                                           Start              
           Dout  &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61581;&#61569;&#61569;&#61569;&#61571;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61580;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61581;&#61569;&#61569;&#61569;&#61571;&#61579;&#61579;&#61579;&#61568;&#61579;
                                                    D11 D10  D9  D8  D7  D6  D5  D4  D3  D2  D1  D0
      
    }}
    
    Sample
                    mov       bit_counter,#20                ' Entire sample routine clocks twenty bits  
                    mov       t1,#%1_1000                    ' t1 contains Start, SGL/Diff, A2, A1, and A0 bits
                    or        t1,Channel                     ' Channel contains a value 0 to 7 (%000 to %111)
                    shl       t1,#32-6                       ' move start, SGL/Diff, A2, A1, and A0 to upper bits of t1
                                                             '  plus 1 bit to clock while CS is high before sending the start bit
                    mov       cnt,delay_time                 ' The MCP3208 datasheet specifies a 250ns minimum time for clock pulses                                                
                    add       cnt,cnt                           
                    andn      outa,CLK_mask                  
    :loop
                    cmp       bit_counter,#14       wc,wz    ' Determine if header has been sent
          if_ae     or        dira,D_mask                    '  Make D_mask an output if it hasn't 
          if_b      andn      dira,D_mask                    '  Make D_mask an input if it has
                    shl       t1,#1                 wc,nr    ' Move the msb of t1 into C, do not update t1
                    muxc      outa,D_mask                    ' Output the bit (only works while D_mask is an output)
                    waitcnt   cnt,Delay_time                  
                    or        outa,CLK_mask                  ' Output a high on the clock
                    test      D_mask,ina            wc       ' Read a bit from D_mask into C
                    rcl       t1,#1                          ' Rotate C into the lsb of t1 
                    waitcnt   cnt,delay_time                 
                    andn      outa,CLK_mask                  ' Output a low on the clock
                    andn      outa,CS_mask                   ' Output a low on chip_select - Only needs to be high for the first clock
                    djnz      bit_counter,#:loop             ' Repeat twenty times
                    and       t1,_4095                       ' Mask the 12 bits of the result
                    or        outa,CS_mask                   ' Output a high on chip_select                                                   
    Sample_ret      ret
    
    Okay, I guess that was a bit complicated with 15 different instructions, but can you at least see how it works with the comments and the signal diagram?
  • tonyp12tonyp12 Posts: 1,951
    edited 2014-01-02 16:35
    ANDN inverts the Source mask before it ANDs the destination, if you want to clear a specific bit (you don't care if current state of it's a 0 or 1)
    If your AND mask is all 1s except the bit you want to go zero then all the 1 ones in destination will stay 1 as 1&1 =1 and a 0 &1 =0 so zeros will stay 0
    The bit location that is a 0 in the mask (after inversion) will result in a forced 0 as 1&0=0 and 0&0=0

    Form a msp430 perspective calling it BitClear makes it easier to understand: BIC.W not.src .and. dst → dst

    Could you live without a ANDN, sure you could invert the mask by hand or use NEG first to invert the mask.
    As you only have 496 lines of code, every trick to get something done in one line is good that is why there is cmpsub, muxz, and sumz etc
  • __red____red__ Posts: 470
    edited 2014-01-02 19:45
    example i use the andn instruction extensively to read a bit because it eliminates the need to learn a new command in the middle of what is already pretty confusing code.
    the learning process has to be as "simple and stupid as possible" if it is going to work for a complicated system. I tried to keep it simple. Too simple for some.


    ... and this is the kind of trap that a technical editor will catch. 95% of the art of writing a GREAT technical book is in charting the order in which you teach to minimize dependencies and make sure you are not forced to teach too much at one time.

    If you're having to contort the language in an example to use previously taught opcodes in a way that a "native speaker" wouldn't, you probably need to review that section.

    If you teach it that way, people will use it even after you've taught then the "native speaker" method later.
  • frank freedmanfrank freedman Posts: 1,983
    edited 2014-01-02 20:01
    ChrisGadd wrote: »
    The book might be for beginners, beginners, beginners, and absolute beginners, but this thread is about Propeller Assembly for beginners.

    There are a total of 78 PASM instructions, many of these are variants of other instructions, and many others are strongly similar.

    If you can understand ANDN, you can understand AND, TEST, and TESTN.
    If you understand SHL, you should be able to understand SHR, ROL, ROR, RCL, and RCR.
    If you understand SUB #1 wz / if_z JMP, you absolutely should be able to understand DJNZ.
    There is nothing sophisticated about any of those.

    Out of those 78 instructions, there are just over a dozen dissimilar ones that I use regularly. I don't think that's beyond the ability of a beginner to learn. Those instructions are certainly easier to understand than the inner workings of a chip like the MCP3208.

    You mentioned Chip Gracey's MCP3208 object, and I agree that it is a very elegant object and not something I'd expect a complete beginner to to be able to write. It should not be too difficult to understand however. I used it as the basis for my own driver:
    {{
      This sample routine is based on code from Chip Gracey's MCP3208 12-bit/8-channel ADC Driver v1.0
      The data-out and data-in pins are tied together and are operated on by D_mask
      A single register, t1, is used for sending the configuration bits and also for receiving the data bits.  Data is sent from the upper bits and read into the lower bits
      D_mask is initially set to an output in order to transmit the configuration bits, and then changed to an input to receive the data bits
    
           __
           CS    &#61574;&#61574;&#61574;&#61574;&#61574;&#61574;&#61573;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61570;&#61574;&#61574;&#61574;&#61573;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;&#61569;
           
           CLK   &#61579;&#61579;&#61577;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574;&#61573;&#61569;&#61570;&#61574; 
                     1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  1   2   3   4   5   6   7   8   9 
                                      
           Din   &#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61578;&#61574;&#61574;&#61574;&#61575;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61578;&#61574;&#61574;&#61574;&#61575;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;&#61579;
                       &#61600;   &#61600;   &#61600;   &#61600;   &#61600;                                                               &#61600;   &#61600;   &#61600;   &#61600;   &#61600;  
                       &#9474;   &#9474;   A2  A1  A0                                                              &#9474;   &#9474;   A2  A1  A0 
                       &#9474;   SGL/Diff                                                                    &#9474;   SGL/Diff       
                       Start                                                                           Start              
           Dout  &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61581;&#61569;&#61569;&#61569;&#61571;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61568;&#61579;&#61579;&#61579;&#61580;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61581;&#61569;&#61569;&#61569;&#61571;&#61579;&#61579;&#61579;&#61568;&#61579;
                                                    D11 D10  D9  D8  D7  D6  D5  D4  D3  D2  D1  D0
      
    }}
    
    Sample
                    mov       bit_counter,#20                ' Entire sample routine clocks twenty bits  
                    mov       t1,#%1_1000                    ' t1 contains Start, SGL/Diff, A2, A1, and A0 bits
                    or        t1,Channel                     ' Channel contains a value 0 to 7 (%000 to %111)
                    shl       t1,#32-6                       ' move start, SGL/Diff, A2, A1, and A0 to upper bits of t1
                                                             '  plus 1 bit to clock while CS is high before sending the start bit
                    mov       cnt,delay_time                 ' The MCP3208 datasheet specifies a 250ns minimum time for clock pulses                                                
                    add       cnt,cnt                           
                    andn      outa,CLK_mask                  
    :loop
                    cmp       bit_counter,#14       wc,wz    ' Determine if header has been sent
          if_ae     or        dira,D_mask                    '  Make D_mask an output if it hasn't 
          if_b      andn      dira,D_mask                    '  Make D_mask an input if it has
                    shl       t1,#1                 wc,nr    ' Move the msb of t1 into C, do not update t1
                    muxc      outa,D_mask                    ' Output the bit (only works while D_mask is an output)
                    waitcnt   cnt,Delay_time                  
                    or        outa,CLK_mask                  ' Output a high on the clock
                    test      D_mask,ina            wc       ' Read a bit from D_mask into C
                    rcl       t1,#1                          ' Rotate C into the lsb of t1 
                    waitcnt   cnt,delay_time                 
                    andn      outa,CLK_mask                  ' Output a low on the clock
                    andn      outa,CS_mask                   ' Output a low on chip_select - Only needs to be high for the first clock
                    djnz      bit_counter,#:loop             ' Repeat twenty times
                    and       t1,_4095                       ' Mask the 12 bits of the result
                    or        outa,CS_mask                   ' Output a high on chip_select                                                   
    Sample_ret      ret
    
    Okay, I guess that was a bit complicated with 15 different instructions, but can you at least see how it works with the comments and the signal diagram?

    Nice chunk of code, doubt I would have come up with your way of setting up the chip in the same sequence as actually reading out the value. Neat!

    FF
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2014-01-03 22:13
    Thanks Potatohead, ChrisGadd, and Tonyp12 for your input on my "andn" question. You're help transformed
    andn into a simple instruction.

    I finally understood that piece of code tonight, I have been reviewing your advice for the last couple days. I was
    really hung up on why there wasn't a mov instruction to link "temp with dat_red."

    I really needed to understand the program before I actually tried it. Thanks Harprit and ChrisGadd. Chris, I am
    beginning to understand your last post, I will keep working on it.



    I have one other question about programming for the mcp3208. The data sheet stated: "If the mcp3208 was
    powered up with the CS pin low, it must be brought high and back low to initiate communication."

    If all Propeller i/o pins are set as inputs during start up, is it possible the CS pin was low?

    I looked at Chip's and Johnny Mac's code and I didn't see any code that toggled CS one time only to
    initiate communication.


    Thanks

    Bill M.
  • ratronicratronic Posts: 1,451
    edited 2014-01-04 08:14
    Bill at the beginning of Chip's assembly program the "spin" (CS pin) in Spin is transferred to "smask" (CS pin) in the assembly program.

    Edit: If you used Chip's MCP3208 object correctly it toggles the CS pin as it is supposed to.

    This sets the CS pin low
    andn outa, smask
    

    This sets the CS pin high
    or outa, smask
    

    Look for those instruction's in Chip's assembly program
  • rwgast_logicdesignrwgast_logicdesign Posts: 1,464
    edited 2014-01-04 08:27
    I stopped following this thread a long time ago, but have been waiting for this book to come out for a long time. Reading the last two pages of this thread it looks like the book is available?? I typed the title in to google but couldn't find anything related to this book except the thread... If propeller assembly for beginners is out how much is it, and where can you buy it?
  • PublisonPublison Posts: 12,366
    edited 2014-01-04 08:44
    I stopped following this thread a long time ago, but have been waiting for this book to come out for a long time. Reading the last two pages of this thread it looks like the book is available?? I typed the title in to google but couldn't find anything related to this book except the thread... If propeller assembly for beginners is out how much is it, and where can you buy it?

    It's been out since March.

    Post #740 tells you how to get it. (Direct from the author)
  • w4fejw4fej Posts: 264
    edited 2014-01-05 08:45
    Hi Harprit:

    I have my credit card out, where do I pre-order your PASM book?? I have your Beginners book and love it and refer to it often in my attempt to learn and use the Prop...

    Waiting patiently for your new book...

    Mike B. North Carolina
  • PublisonPublison Posts: 12,366
    edited 2014-01-05 09:13
    w4fej wrote: »
    Hi Harprit:

    I have my credit card out, where do I pre-order your PASM book?? I have your Beginners book and love it and refer to it often in my attempt to learn and use the Prop...

    Waiting patiently for your new book...

    Mike B. North Carolina

    See Post #808 (above) or go right to Post #740
  • HarpritHarprit Posts: 539
    edited 2014-01-05 10:49
    Mike
    I'm too little for credit cards
    Send me $35.00 via paypal will mail it as soon as I can get out of my drive. We are in for 10 inches of snow
    I'll send you the code file right away after receiving your order
    H
Sign In or Register to comment.