Shop OBEX P1 Docs P2 Docs Learn Events
Assembly Documentation & Half-Duplex Serial Receiver — Parallax Forums

Assembly Documentation & Half-Duplex Serial Receiver

Timothy D. SwieterTimothy D. Swieter Posts: 1,613
edited 2006-06-13 23:38 in Propeller 1
I was curious when more assembly documentation for the Propeller would be released?

I am currently trying to do a DMX receiver. I am realizing that the speed of DMX (250K BAUD - 4us bit, 320 Clock Cycles) means that I need to be doing this in assembly. I started by reviewing the FullDuplexSerial Object (thinking maybe I could use just the receive portion of the assembly routine) and looking at the Assembly Elements PDF. It has been a while since I did something in assembly, but I think I can get through it with a little more documentation (and maybe more help from this forum).

If someone has already developed an assembly half-duplex driver, I loved to see that too! No sense reinventing the wheel.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter
www.tdswieter.com
One little spark is all it takes for an idea to explode

Comments

  • edited 2006-06-09 20:40
    Look in the Propeller Tool \ Examples \ Library folder for an object called Monitor. Here's the default install path: C:\Program Files\Parallax Inc\Propeller Tool v0.95.1\Examples\Library. The Monitor object has two methods you can use for half duplex (or to make a half duplex object). The are named serout and serin.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2006-06-09 21:39
    Thanks for pointing me towards Monitor - I had not reviewed that yet. The routine I started to develop is similar to "PRI serin" method of Monitor (Monitor method posted). I developed my method by reading the Propeller documentation and looking at other example files. I too had waitcnt setup for the consistent timing, but I think that is where the downfall of my program is happening because of the 250K BAUD rate of DMX.

    PRI serin : b | t
      waitpeq(0, |< rx, 0)
      t := cnt + baud >> 1
      repeat 8
        waitcnt(t += baud)
        b := ina[noparse][[/noparse]rx] << 7 | b >> 1
      waitcnt(t + baud)
    
    



    The variable baud, as defined by monitor (and similarly my program), is 320 for DMX. I have observed with my program, that 320 clock cycles had elapsed before I got to waitcnt(t += baud) thus my program would hang for a minute until the counter came back around. Beasue of this, I was thinking I needed to try and have a routine in assembly. I can experiment more with it, but I don't have any more instructions then you do between the intial logging of cnt and the waitcnt.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter
    tdswieter.com
    One little spark is all it takes for an idea to explode
  • edited 2006-06-09 21:47
    Timothy,

    Sorry about that, I misread your post. You wrote 250K, but I was reading too quickly, and saw 2400. So, I thought the spin version would work fine, but as you pointed out, the spin waitcnt command doesn't work for times that small.

    Regards, Andy
  • edited 2006-06-09 22:19
    Well, taking a look at the FullDuplexSerial.spin assembly code, it looks like the serial driver is always bouncing back and forth between the transmit and receive routines during each bit. Take a look at the following commands:

    - mov txcode, #transmit
    - mov txcode #receive
    - jmpret rxcode, txcode

    I think it might be possible to rearrange the placement of these commands so that only jumps from the to transmit to the receive (or the other direction) when the buffer is empty (or with 17/19 software flow control, or hardware flow control).

    It would be nice to simply add a mode bit to the start method for half duplex. I don't see exactly how to do it on my first examination of the code.· It seems like it should be possible though.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2006-06-09 22:26
    Hey no problem man. I thought maybe I was doing somethign wrong and appreciated the advice to check it out - makes me double check my work. I see the the waitpeq commands are available in assembly, does it have the same parameters?

    I also thought it would be nice if FullDuplexSerial would have a mode bit for half/full operation. I will look more into the assembly routine tomorrow and see if I can understand it more.

    Andy, do you know when more information on Propeller assembly language will be available? I appreciate your help.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter
    tdswieter.com
    One little spark is all it takes for an idea to explode
  • edited 2006-06-09 23:03
    It'll probably be a two to three weeks before the assembly language chapter is available.

    In the meantime, a document I find really helpful is called Core Docs.pdf, which should be in the Propeller Tool folder at the same level as Propeller.exe. It's got a table with all the assembly commands on page 5 and a lot of useful assembly information throughout.

    You'll see on page 5 that the waitpeq instruction is

    WAITPEQ D, S

    It also says that the destination (D) is equal to INA ANDed with the source (INA & S). What that really means is that INA is ANDed with C, and the program waits for that result to be equal to D.

    I just found out from our software engineer that when you use this command, make sure to clear the C flag; otherwise, it'll checking port-b, which doesn't exist on the 32 I/O version of the chip.

    Post Edited (Andy Lindsay (Parallax)) : 6/10/2006 3:33:46 AM GMT
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2006-06-12 13:32
    Thanks for pointing me towards Core Docs.pdf. How many times have I been in the Propeller Tool Folder and did not notice this document?

    My weekend ended up being too busy to start investigating the assembly half-duplex idea. Maybe later this week.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter
    tdswieter.com
    One little spark is all it takes for an idea to explode
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2006-06-13 20:40
    Andy,

    You mentioned to clear the C flag just before using waitpeq. What is the best way to do this? Is it simply done by add #0, #0 wc or is there a better way?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter
    tdswieter.com
    One little spark is all it takes for an idea to explode
  • PyrotomPyrotom Posts: 84
    edited 2006-06-13 21:16
    I've been working on an assember half-duplex receiver, and have it working (for the most part), but have a few questions. Here is the core code I'm using, which is based on the FullDuplexSerialexample.

    
                            rdlong  bitticks,t1             '   cycles between MIDI bits
                            mov     halfticks,bitticks
                            shr     halfticks,#1
    
                            mov     noncmd,#receive
                            mov     newnote,#receive
    '
    ' Receive
    '
    receive              test    rxmask,ina      wc      ' Wait for start bit      
           if_c            jmp     #receive
    
                            mov     rxbits,#9               ' Ready to receive byte
                            mov     rxcnt,halfticks
                            add     rxcnt,cnt                          
    
    :bit                   add     rxcnt,bitticks          ' Ready next bit period
    
    :wait                 mov     t1,rxcnt                ' Check if bit receive period done
                            sub     t1,cnt          wz
            if_nz         jmp     #:wait
    
                            test    rxmask,ina      wc      ' Receive bit on rx pin
                            rcr     rxdata,#1
                            djnz    rxbits,#:bit
    
                            shr     rxdata,#32-9            ' Justify and trim received byte
                            and     rxdata,#$FF
    ''
    '' A byte has been received
    ''
    
    



    I have two questions about this code. First, if I take the two lines
                            mov     rxcnt,halfticks
                            add     rxcnt,cnt                          
    
    


    and instead make them
                            mov     rxcnt,cnt
                            add      rxcnt,halfticks
    
    


    things stop working. Why? I always thought a+b = b+a..... The second question is that the value of halfticks has to be EXACTLY one half of bitticks for the code to work. Again, why? The way I understand it, that is just positioning the TEST instruction to the middle of the bit time, and it should not be that sensitive.
  • PyrotomPyrotom Posts: 84
    edited 2006-06-13 21:19
    One more note - the value of bitticks I'm using is 2560 at 80 mhz for the MIDI baud rate of 31.25khz.
  • edited 2006-06-13 22:03
    Timothy,

    Sorry, my mistake. It doesn't matter what the C bit stores in the current 32 I/O pin chip. Apparently, that feature is on the drawing board for a 64 I/O pin chip.

    Yes, if you have to clear C, use a command that won't carry along with WC.

    Andy
  • edited 2006-06-13 22:16
    Pyrotom,

    It looks like there is a bug in the modified program that has it really close to the edge as far as timing is concerned. In both of your observations, tiny changes in timing are pushing it over the edge. (A + B and B + A are not equal in this case because cnt will store a different value.) If you try those small changes in the original code, it should still work, even at much higher baud rates.

    I've also been wanting to try my hand at adding a half duplex option to FullDuplex.spin. Maybe when I get further into it, I'll see the problem, but right now, I don't.

    Andy
  • PyrotomPyrotom Posts: 84
    edited 2006-06-13 23:38
    Arrgh, I found the problem. My own cleverness got me. I had replaced the original wait loop of
    :wait                   jmpret  rxcode,txcode         'run a chuck of transmit code, then return
    
                            mov     t1,rxcnt              'check if bit receive period done
                            sub     t1,cnt
                            cmps    t1,#0           wc
            if_nc           jmp     #:wait
    
    


    with
    :wait                 mov     t1,rxcnt                ' Check if bit receive period done
                            sub     t1,cnt          wz
            if_nz         jmp     #:wait
    
    


    which is not the same thing at all. My code had to hit zero exactly - it's a wonder I ever got it to work!
Sign In or Register to comment.