DF1 protocol, DLE's and 16's


Thread Starter

Bill S

I am writing a serial DF1 protocol for home use. It works for the most part - CRC calc is fine, writing to B3 is fine, writing to N7 is fine. But reading from N7 is giving me a slight headache, mainly because of the double transmission of chr$(16) when a 16 is in the data string.

If the protocol did NOT do this, it's trivial to calculate how many bytes I should receive, parse the data, then move on to other things. But how does one handle getting back 4 words of data from N7 when the data is actual numbers such as:
4112 - represented as 16 16 16 16
4112 - represented as 16 16 16 16
784 - represented as 16 16 3
1206 - respresented as 16 16 5

How does one know if the string from the PLC is finished? All the redundant 16's destroy any chance of me using any accurate string length comparison. I cant look for the end of string (16 - 3) because that's part of 784. I cant look for the many 16 - 5's I get from the PLC because that is part of 1206.

I dont want to use a timer and assume the data gets to me in x seconds. (Perhaps I need to?)

Too bad they had to do it this way (I know they did it for a reason, unknown to me though).

Maybe there is a way to turn off the double transmission?

Thanks for any tips!

Robert Scott

DF1 Protocol uses DLE as an Escape character. This allows a simple distinction between data and administration bytes. If a DLE just happens to show up in normal binary data, as you have indicated, then it must be doubled so that you know it is not part of a defined administrative sequence. The DLE-DLE pair is interpretted as a single DLE.

When you parse DF1 protocol upon reception, you should not be relying on counts or timers. You should just process the bytes one at a time through a state machine in your code. In state 0, if you see a non-DLE byte, just put it in your buffer and advance the buffer pointer (or index) and accumulate it into your CRC calcuation. If you see a DLE in state 0, then don't transfer anything to the buffer. Just transition to state 1 and go on to parsing the next byte. When you are in state 1, then the byte you are looking at should be interpretted as the second byte of a DLE-? pair. The second byte could be any of STX, ETX, ACK, NAK, ENQ, or DLE. If it is STX, then you should discard whatever is in your buffer and start at the beginning. Also reset your CRC calculation. If it is ETX then your buffer is complete, but you should transition to state 2, meaning that you are now expecting to see CRC bytes. (By the way, the ETX counts in the CRC calculation but the STX does not.) If it is an ACK or a NAK, you can just set a flag to record the fact. If it is an ENQ, then you should respond by sending a ACK or a NAK back to the sender, depending on the results of the most recent CRC comparion. If it is a DLE, then put a single DLE into the buffer as a normal data byte. Now in state 2, take the next byte as the LSB of the CRC and transition to state 3. In state 3, take the next byte as the MSB of the CRC and go back to state 0. You can now check the received CRC against the one that you calculated as you filled the buffer. Set a ACK/NAK flag depending. If it is a NAK, then discard the buffer. If it is a ACK, then you may now interpret the contents of the buffer. Notice that the CRC is special because if a DLE happens to show up as one of the bytes, it is not replaced by DLE-DLE. So you can depend on getting exactly 2 bytes of CRC, which is what the state machine that I described does.

As you see there is no reason to worry about exactly how many bytes are going to be received. Just read them one at a time until the state machine is satisfied.

Robert Scott
Real-Time Specialties
Embedded Systems Consulting
Bill, I hope you have some alternate reason for wanting to write (and learn) the DF1 protocol, other than home use that is. For that application DF1 is a bit of a sledgehammer. In any case, you said you can write to N7 files fine, so do you do what is called DLE stuffing? This should be a separate routine that examines the data content (not the frame) of the message you have assembled, and are ready to send, and byte by byte where ever it finds a DLE (hex 10) inserts another one. You should do the same thing in reverse, before interpreting the data content of the received message. The DLE is an escape character that serves to flag to a command interpreter routine that the next character is likely a byte defining something about the message (for instance DLE STX or DLE NAK). When the second character is another DLE the command interpreter routine can be exited, the data content of the message just happened to be hex 10 (as is the case with your example of 4112 which is hex 1010, each byte of text being stuffed with another one to end up in hex 10 10 10 10).

DLE stuffing is part of the DF1 protocol and can not be turned off. The reason for it is bound up in the peer to peer nature of the protocol. It is possible for an initiating station to receive back several messages fragmented and interspersed.

Why am I doing this, I'm trying to forget about DF1.