Shop OBEX P1 Docs P2 Docs Learn Events
Edge Detection — Parallax Forums

Edge Detection

pgbpsupgbpsu Posts: 460
edited 2007-09-18 14:27 in Propeller 1
I'm having trouble getting a quick and clean way to recognize a rising OR falling edge. I'm trying to maximize the rate at which data are passed from the Prop into another device. Data from the Prop are placed on the output pins. When these data are valid, the prop drops a line telling the other device they should be read. The other device sees that, then reads the data. Once it has read the data, it flips a line indicating that the propeller should get the next chunk of data ready. There is no way to tell what state the line coming into the Prop will be in when the whole thing starts. Furthermore, it needs to recognize the opposite transition for the next chunk of data. So, I can't simply ask the prop to wait for a rising edge or to wait for a falling edge. The propeller needs to recognize any transition on that line.

My first effort was along the following line:
put data out and wait for response...
        and      IN_PUT, ina nr, wc         ' Set C= current state of pin
        muxc    toggle, IN_PUT              ' set toggle[noparse][[/noparse]IN_PUT]=C
        waitpne toggle, IN_PUT              ' wait until IN_PUT != toggle



move on to next chunk of output data....

This didn't give the result I was hoping for. So I either got the code wrong, or this approach just doesn't work.

I was hoping there was something simpler (and faster if possible- since I'm passing 8 bits of a 32 bit sample at a time, this happens 4 times before I can move on so a single extra instruction becomes 4). I've seen lots of stuff in the forums about using the counter in rising or falling mode, but nothing about using them as a rising AND falling edge detector.

Does anyone have any suggestions? The process needs to be done in assembly so that my transfers happen just as quickly as possible.

Thanks,
Peter

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2007-09-16 03:39
    What you describe sounds almost like a fully-interlocked handshake. I think if you were to implement this handshake in its usual form, your job would be a little easier. This involves two handhsake lines:

    1. DAV (data available) controlled by the sender.
    2. RFD (ready for data) controlled by the receiver.

    In practice, both lines start out low. From there the protocol works like this:

    1. When receiver is ready for more data and sees DAV low, it raises RFD.
    2. Sender, upon seeing RFD high, puts data on data bus.
    3. Sender raises DAV.
    4. Receiver, upon seeing DAV high, reads data.
    5. Receiver lowers RFD.
    6. Receiver processes data.
    7. Sender, upon seeing RFD low, lowers DAV.
    8. Go to 1.

    The procedures for each are as follows:

    SENDER

    1. Wait for RFD to go high.
    2. Put data on bus.
    3. Raise DAV.
    4. Get next data ready to send.
    5. Wait for RFD to go low.
    6. Lower DAV.
    7. Go to 1.

    RECEIVER

    1. Wait for DAV to go low.
    2. Raise RFD.
    3. Wait for DAV to go high.
    4. Read data from bus.
    5. Lower RFD.
    6. Process received data.
    7. Go to 1.

    In this way, each device is waiting for a certain level to appear on the handshake lines, not for an arbitrary edge.

    -Phil

    Post Edited (Phil Pilgrim (PhiPi)) : 9/16/2007 3:46:03 AM GMT
  • IAN STROMEIAN STROME Posts: 49
    edited 2007-09-16 03:41
    Hi,
    This is only in psuedo code but should be about there.

    set data line(s) = output \ set data direction reg for output
    set ack line = input \ to read initial acknowledge state
    read ack line to (ACKVAR) \ put ack in variable ( 1 or 0 )
    loop1 invert (ACKVAR) \ NOT ie 1=0;0=1
    set ack line = output \ set ack data direction for ouput
    GET YOUR DATA HERE
    output data to data line(s)
    output (ACKVAR) to ack line
    set ack line = input \ get ready for response
    read ack line
    notready IF ack line value <> (ACKVAR) THEN loop1
    ELSE notready ENDIF

    sorry about the code, have only just wired up the rest of my homebrew prop
    board, so haven't had a look @ the ASM yet.

    Regards Ian

    Also this device you're talking to, is it perhaps open collector??

    :- So what's the speed of dark??
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-16 07:32
    What Phil describes is a good future protocol; the current protocol however is not clear to me. Saying "it flips a line" will not help. When exactly is the line Phil calls RFD set and reset?

    Also: Why do you need "edge detection"? The Prop is excellent in waiting for a state...

    Post Edited (deSilva) : 9/16/2007 11:41:06 AM GMT
  • pgbpsupgbpsu Posts: 460
    edited 2007-09-16 12:33
    Hi Phil-

    Thanks for the suggestion. In fact, that's where my code began. However, in my attempt to speed things up as much as possible, I moved to the design in my earlier post. By doing this I am (potentially, if I can get it working) removing half the handshaking.

    sender: The prop starts with DAV high.
    sender: When it has the first chunk of data ready, lower DAV and start watching for RFD to change state
    receiver: The receiver is watching DAV. When it sees DAV go low, it reads the data.
    receiver: flip RFD line (toggle is a better word, but what I mean is set RFD to ~RFD)
    sender: Watch RFD line, when it changes state, raise DAV and remove the data.
    repeat.

    As you mentioned, this is very close to the protocol you laid out, but it saves instructions on both the receiver and the Prop.
    deSilva said...

    What Phil describes is a good future protocol; the current protocol however is not clear to me. Saying "it flips a line" will not help. When exactly is the line Phil calls RFD set and reset?

    Also: Why do you need "edge detection"? The Prop is excellent in waiting for a state...

    Hi deSilva, this is a tweak of my I2S to 8bit write code from a couple of weeks ago.
    http://forums.parallax.com/showthread.php?p=671547
    Poor word choice on my part. By flip I mean change state or toggle. I agree that the prop is great at waitpne or waitpeq. Problem is I don't know what state (0 or 1) I'm waiting for. The only thing I know about the state I'm waiting for is that it is the opposite of the state I'm currently in. If I knew the starting state, I could predict whether I'd be waiting for a 0 or 1. But I don't know that. The line Phil calls RFD is set to ~RFD as soon as the receiver has read the data. That's the edge I'm trying to detect.

    I haven't tried this (and can't since I'm at home and prop setup is at work) but maybe all I need is:
    waitpeq RFD, ~RFD              ' wait until RFD != RFD
    
    


    This assumes that waitpeq will store the state of RFD when it starts the command, then begin waiting for RFD (the pin) to change state. That's an assumption on my part as to how waitpeq works. If I'm wrong about that, it will be waiting for RFD != RFD which could result in a LONG wait.

    Ian, I appreciate your input, but I'm trying to reduce this transfer speed by a hundred or so nanoseconds which means this has to be done in Assembler.
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-16 13:31
    Let me recapitulate:
    The state of the signal has no meaning, only the "flip" AFTER you set your "data ready"

    So "in the very beginning" the device must be ready to accept data!? This should be your starting level!
    I assume the device will not "flip" the line for other reasons but a "data ready" completion.

    Then:
       AND    flip_pin_mask, INA  WZ
       OR      OUTA, data_ready_pin_mask
    
    ... do other things, but don't touch Z ....
    
       IF_Z   WAITPEQ  flip_pin_mask, flip_pin_mask
       IF_NZ WAITPEQ  flip_pin_mask, #0
       ANDN  OUTA, data_ready_pin_mask 
    
    


    should work...
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2007-09-16 15:43
    Your protocol might work, but only if both sides can agree on what the initial conditions mean. And since each side may start (or restart) asynchronously, that could be a problem, unless you also incorporate some sort of timeout mechanism. Otherwise, you could end up deadlocked.

    -Phil
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-16 16:02
    There can be a problem, if the device
    (a) is in an undefined state longer than the Propeller needs to start requesting its data
    (b) "flips" just between my first and second instruction without any obvious reason
  • pgbpsupgbpsu Posts: 460
    edited 2007-09-17 01:06
    Phil and deSilva-

    Once again, thanks for your input.

    Phil, I believe the protocol can work. You are correct that both sides will need to know the rules. I believe the only thing both sides need to know is that the receiver can and should only read data when DAV is low. And that the propeller should not move forward until RFD changes state.

    I think I muddied the waters a bit by including the protocol in the first place. What I'm really after is a fast and simple way to see if a line changes state (what I'm calling edge detection).

    deSilva-

    Re: your concern b:
    (b) "flips" just between my first and second instruction without any obvious reason
    The only thing that changes the state of RFD is a successful read of the data.

    Re: your concern a:
    (a) is in an undefined state longer than the Propeller needs to start requesting its data
    I'm not sure I follow, but the Prop should put out the first piece of data regardless of the state of the listening device. It should put those data on the lines just as soon as it gets them, even if no device is listening. However it should NOT proceed to the next byte until is has received a signal from the listening device. Once again, that's protocol and not really what I'm worried about.

    The code you suggested will most certainly work. But it takes more overall instructions than simply checking the current state of in the input pin (step 1), moving that to a variable (step 2), outputting the data (which I don't count since that needs to be done no matter what the protocol or method of identifying a change of state), then waiting for the state of the input pin to change (step 3).
    and         RFD, ina nr, wc                   ' Set C= current state of RFD
    muxnc     wait_for_state, RFD             ' set wait_for_state = !C;
    
    


    put the data out and do other things as necessary
    waitpeq    wait_for_state, RFD             ' wait until RFD = wait_for_state
    
    



    This also doesn't care what happens to Z along the way. I'll have to keep working at this because I don't see any reason why this won't work. However, as I indicated in my original post, I'm still on the lookout for something that doesn't require 3 instructions. Possibly taking advantage of the CNTA &/or CNTB, but I don't know how to do that.
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-17 07:01
    It is quite simple (perhaps the Parallax AN001 will help?), but it would take more instructions, as you have either to reset the counter each time, or remember the old value...
  • BradCBradC Posts: 2,601
    edited 2007-09-17 07:24
    Why not something like this? Same number of instructions tho..

    mov tmp, ina ' Get the current input value

    xor tmp, rfd_mask ' Just invert the one bit you are after

    waitpeq tmp, rfd_mask ' Wait until that one bit changes state

    where rfd_mask is a single 1 aligned with the rfd pin
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-09-17 12:11
    This sounds like usb's nrzi protocol. Maybe the various recent usb applications can help you.

    http://en.wikipedia.org/wiki/NRZI

    Post Edited (Fred Hawkins) : 9/17/2007 12:17:28 PM GMT
  • pgbpsupgbpsu Posts: 460
    edited 2007-09-18 14:27
    Here's the code I finally used to detect a change of state on a single pin (RX_OK). Thanks to everyone for their input.

                  and         RX_OK, ina nr, wc       ' Set C=state of RX_OK
                  muxnc     toggle, RX_OK           ' toggle[noparse][[/noparse]RX_OK] = ~C
                  waitpeq   toggle,RX_OK            ' wait for RX_OK to change state
    
    



    where RX_OK is the pin to watch and toggle is a variable.

    Hope this helps someone else out there.
    pb
Sign In or Register to comment.