Confused about synchronous communications

Sep 20, 2007 29 Replies

I'm trying to implement a general prarallel port communications program but I'm a little confused about the timing issues involved.



In all of the protocols I'm looking at(I2C, SPI, and ICSP) it seems that the communications is edge triggered.



What I see is that a data bit is sent when the clock changes and then the clock changes again.



something like


Data /---------\\ / \\ / \\----


\\ /---\\ \\ / \\ \\---/ \\---/ Clock


So is this normally the case? Also, when does the data have to be valid? On the second edge transition? (So in some sense the clock is 2x the data rate so actually the data would be sampled 1/2 inbetween the data transfer rate?)



Basically I'm trying to figure out how I am to write my routine as at the moment I'm and just changing the clock with the the data but then I realized that there is no way to keep it synched up perfectly.



I also thought about sorta offseting the clock half way sorta like the above but with



Data /---------\\ / \\ / / \\---------/


/---------\\ / \\ /



------/ \\---------/ Clock



But then this has a problem of the data changing towards the end of the clock.



So, I guess my actual question is, when is it required for the data to be valid?


Data /*****-----\\ / \\ / \\----


\\ /---\\ \\ / \\ \\---/ \\---/ Clock



Do I have to get "valid data" at **** so that it can be sampled by every other edge(every rising edge in this case)? If so, is this pretty much how all synchronous communications works?



Thanks, Jon


I guess what I'm asking is if the data needs only to be valid on the rising edge(or falling edge) of the clock and maybe a little after... and hence by having the clock rate 2x faster it will "sample" it in the middle of the data which means I have about 1/2 the clock to get the data there?

you have to meet set up and hold times, this is the time before and after the clock edge used to clock in the data that the data has to be valid often the most conveneint way to do this is to make the data change on the opposite clock edge.

so in your first diagram this would be the case with the clock rising edge clocking in the data, and the data changing on the falling edge.

if you try to change both the clock and the data always at the same time then what you have is double data rate, this is more complicated and generaly uneccessary unless you are going after very high data rates and wish to reduce the inteference from the clock signal.

Colin =^.^=

also, does this pretty much get all synch'ed communication? I know(I think ;) there are such things as level triggered but are they really used for commerical devices? Bascailly do I have write a routine for both types? or will get pretty much cover everything with edge triggered?

On a sunny day (Thu, 20 Sep 2007 22:28:37 GMT) it happened "Jon Slaughter" wrote in :

Depends on the system. Some systems data is clocked in on the positive edge of the clock, and in some systems it is clocked in on the negative edge.

And, there could be systems were data is latched when the clock is high, and systems where data is latched when the clock is low......

In i2c you need to pay especialy attention to start and stop sequences too..

Look at the datasheets is all I can say.

On a sunny day (Thu, 20 Sep 2007 22:33:53 GMT) it happened "Jon Slaughter" wrote in :

Imagine a 74HC74 D flipflop. It is positive edge triggered. If you put data on the D input, and send the clock from 0 to 1, that data will appear on the Q output.

After it has changed state (respect hold time) you can do with data what you want, and lower clock whenever you want (after min clock hold time).

Again look at the datasheets, it should be there.

Jon,

I'm not sure it's safe to generalize. My advice is to refer to the data sheet for your device of interest and see what the manufacturer wants and expects.

In general, though, it looks like you have the general principle down pat.

When I'm bitbanging, I don't try to center the clock, as a rule. I put my data up, then immediately toggle a clock pulse. Next data bit, toggle again. Repeat as necessary, as long as that's within the manufacturer's timing specs.

When I'm reading, I read the data as soon as I detect the appropriate clock transition.

So far, it's worked.

BTW - when reading, make sure you understand the data sheet. You'll find yourself seeing the first data bit present before the first clock pulse. If you don't prepare yourself for that conditon, you'll be chasing your tail.

The data sheet is your friend!

Good luck,

Tom

Yes, I have been looking at it but was confused because I wasn't sure when the data had to be rock solid. It showed the data changing but doesn't say when it has to be ready. I should have known that if its edge triggered then it should be on an edge. But this is the first time I've done any low level communications like this and I just wanted to be sure. The data sheets giving the timing but they assume you already understand the basics.

Just didn't want to assume something that wasn't true and then spend days trying to figure out why my code isn't working.

I'll go ahead and try to implement the stuff down and see what happens. Just a slight modification of my code(sending clock 2x as fast).

Thanks, Jon

Yes, but I don't think that is anything to difficult? I just have to make sure I set the lines correctly and wait atleast the minimum times.

I did but was confused when exactly the data on the data line had to be correct. They show the data edge right and the clock edge rise at the same time. This can't work though and I didn't really notice the clock was 2x as fast ;/ It make sense and everything but I really wanted to make sure before I went any farther with my code(which I essentially have the clock at the same rate as the data(but I was just testing my code with some leds so it wasn't critical).

Thanks, Jon

Yeah, this is exactly what I was going to do. Just that the data sheets don't point that out because I guess its suppose to be implicit. I was thinking, for some reason, that the data had to be valid when it reached level but its just when the edge of the clock is triggered(which ever one it is, which isn't important cause I can just invert the clock I suppose)

Well, thats what I coded

public void SyncSend(ParallelPortPins DataLines, int[] DataBits) { int m = (((int)DataLines) | (int)ClockPin) ^ ((int)InvertedPins); int cp = ((int)ClockPin) ^ ((int)InvertedPins); int clock = cp;

for (int k = 0; k < DataBits.Length; k++) { // Toggle ClockPin clock = clock ^ cp; DataBits[k] = (DataBits[k] & ~cp) ^ clock;

// Send data before clock if ((((int)ClockPin) >> 16) > 0) { Data = (Data & ~m) | (DataBits[k] & m); Control = ((Control & ((m >> 16) & 0xFF)) | ((DataBits[k] & m) >> 16)) ^ (clock >> 16); } else { Control = ((Control & ((m >> 16) & 0xFF)) | ((DataBits[k] & m) >> 16)) ^ (clock >> 16); Data = (Data & ~m) | (DataBits[k] & m); }

Thread.SpinWait(DataRate); } }

Basically I just sendt he clock like its a piece of data but I alternate it every time I send a piece of data. Of course then I thought that this wouldn't work because theres no way to make sure the data would be valid before the clock changed(if it was edge triggered... which I think I was thinking that it was level triggered and thats why I did it).

I just have to change the clock 2x as fast I think and it should work fine. Then I just have to worry about getting it to work within the protocol but I think I can handle that.

Thanks, Jon

Yeah. that was the way I was thinking about it... but the timing diagrams don't show this. They show the data like I graphed it in the OP and not cutting it in half were the data isn't necessarily valid. I was thinking that it had to be valid on the whole level and that it had to do this on the edge.

I think I got it now.

Thanks, JOn

Jon Slaughter? These are the two phrases to get nailed hard into your head... "set up time" and "hold time." You should look them up, but in general the idea is that a digital input needs a certain amount of time while the data is stable __before__ you 'clock it' in -- the set up time. And, that same input requires a certain amount of time that you need to keep that same data stable __after__ you clock it -- the hold time. These surround your clock edge, for edge-triggered inputs.

If you are bit-banging, you can often ignore all if you change the latching clock edge on a different cpu cycle than you change the data

-- because most of the time your bit banging is way, way slower than the digital latch its talking to. So I think a lot of programmers don't even know that it would be a good idea to read a datasheet, just do the same old bit banging they've done in the past, and manage to sneek by in life without getting caught. But in some cases, it can get you hard.

Most cpu datasheets will provide some documentation on the worst case rise time and worst case fall time (often different figures) for their I/O pins relative to the cpu clock cycle. If you change an I/O pin, or think you did on some cpu cycle edge, it really takes place some time later on. If the cpu has multiple clocks per instruction cycle, it may happen synchronous to that internal clock between instructions, plus a little analog delay to that. But if you change the clock edge on a later instruction from the data change, then you are assured of at least one cpu cycle delay, which is usually more than enough. If you try and change two I/O pins at once, the data and clock, then you are probably playing with fire unless you have some reason to believe otherwise. A delay line on the clock pin, for example, or else that the data sheet of the target device says that the setup time is zero and puts the setup+hold into its hold time spec because one is internally delayed relative to the other, perhaps.

Jon

it also depends how fast you are sending and how fast you are polling at the receiving end. if the port you are receiving with doesnt actually 'clock' the data in then you have to make sure you poll it fast enough to detect both the high and low state of the clock.

if you are sending quite slow you could actually afford to toggle the clock and change the data at the same time, when the receiving end detects the clock has changed it quickly reads the port again and the data should be stable at that time.

it is sometimes relied on that the hold time is 0 so that the clock and data can be changed at the same time, but this is not good if the clock can be delayed more than the data wich could happen with long cable, it is possible to overcome this by introdicing a delay on the data, some chips have tunable data delays to allow the fastest comunication possible.

Colin =^.^=

ok. I had some intuitive idea about didn't know the exact terms. I was uncertain when the set up time started in the datasheets. I know now though ;)

Yeah, thats why I'm trying to get more information about it. I know I could just bang them and probably get it to work but I'd know enough about it so I don't have any anomalous behavior.

I think I do not have to worry about that though? The clock itself will change 2x as fast and the edge trigger will never change with data because the data is twice as slow. Basically every other edge will change with the data but thats not the edge that triggers so its no big deal which one comes first?

Thanks, Jon

In the synchronous data work I've done, at the business machine interfaces data is transmitted on the positive going clock edge and it is read during the negative going clock edge; for each direction of transmission. The data should be valid for most of the bit-length, but by sampling at the center at the receiver, any affects from jitter will be essentially eliminated.

For my communications I don't have to poll but I will eventually add that ability. There are some major problems that I see with polling because I cannot do it in a consistent way(because of windows). I will try and poll it fast as possible but not sure how its going to work out cause I haven't done any tests.

Ok, I see what your saying. Basically the set up time is "artificial" in that its only used because it takes time to get stable data? So if I know for a fact that I can do something like this

out data out clock

and the setup time is just a few cycles of the then it would work just fine because the data would be valid(by assumption). Of course I'll still needt toggle the clock 2x unless it would be both + and - edge triggered?

Although the problem I have, because I was thinking about using this method which I called "interleaved" where I offset the clock 1/2 the clock freq so its

out data delay out clock delay out data ...

so the clock always changes in the middle of when the data changes(approximately). This wouldn't work with just a single edge trigger though.

The problem I wast thinking is right at the transition between two consecutive data changes. Basically, Does the data have to be valid durring the whole hold time or just basically durning most of it at the start? (I would imagine it depends on the integrity of the clock signal though?)

Well, at this point I'm just trying to do simple I2C, SPI, and ICSP stuff for a few projects I have in mind. I think just "bit-banging" is pretty much going to do it though. Theres just a few issues I wanted to talk about before I moved on so I didn't get down the wrong path.

Thanks, Jon

I'm not sure what you mean by sampling at the center? I shouldn't have to sample anything because I'm in control of the master clock. (So basically I can clock data to and from the slave?)

Although eventually I'll want to do some sorta asynchronous communications and stuff like that were I will need to poll but this is going to be pretty difficult under windows.

Thanks, Jon

If I understand you correctly then you are probably okay. I gather you are saying that you DO change the data and clock at the same time, but that when that takes place it is only on a benign clock change (in other words, the clock edge that doesn't clock in the data but only on the opposite phase.) Assuming set up and hold isn't a problem, that seems okay. And with that terrible-looking c++ code I saw (I didn't check to see when the data changed relative to the latching edge of the clock), I am not much worried about the timing. I don't think they build latches that slow or cpus that fast. ;)

Jon

Its actually C# code.

Essentially what I do is load the bits into an array and output them to the port. But only on lines that are for output. So basically you would call the code like

SyncSend(ParallelPortPins.Data0 | ParallelPortPins.Data1, new int[] { i,j,k,l }); So that the only pins that are changed are the D0 and D1 + clock pins(which is defined inside the class).

So all that mess is just masking out the pins that are to be changed and putting the data in them (the data itself is in a special format and wastes a lot of space but easier to work with(essentially matches the memory mapped port).

The code I send only changes the data with the clock at the same rate... but if I double the clock rate then its should match up just right and if its the wrong edge then I can easily invert the pins.

The main problem now is actually implementing i2c. I'm not sure if I can actually do it because its not clear to me(still reading over the specs) if the clock is always in control of the master when sending and recieving data. Basically I want to avoid polling for this as much as possible because windows makes it a bitch to do.

My initial thoughts where that the master clock was always used to send and recieve data and if thats the case then it shouldn't be a big problem. If slaves take over the clock when they send data then its a problem cause I have no way to know except for polling(or try to implement some interrupt driver in windows which is probably much more trouble than its worth).

I think I'm going to go ahead and try to implement ICSP since that seems to be the easiest and then see what happens.

Thanks, Jon

On a sunny day (Thu, 20 Sep 2007 23:03:38 GMT) it happened "Jon Slaughter" wrote in :

I dunno what sort of code you have, asm, C, BASIC, or whatever, but for i2c you could download C code from Philips IIRC. I have open source drivers in C too, they are in iiclib.c

formatting link
That program does i2c protocol via 3 par port pins.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required