Edge Detection
pgbpsu
Posts: 460
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...
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
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
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
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??
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
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.
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:
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.
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:
should work...
-Phil
(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
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).
put the data out and do other things as necessary
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.
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
http://en.wikipedia.org/wiki/NRZI
Post Edited (Fred Hawkins) : 9/17/2007 12:17:28 PM GMT
where RX_OK is the pin to watch and toggle is a variable.
Hope this helps someone else out there.
pb