You are here: Elements > Frame Transformers > A Frame Transformer for FP

A Frame Transformer for FP

To see what a simple Frame Transformer is like, let us look at one for our Fictitious Protocol. You might have noticed a flaw in the FP design (as presented prior to this point). On the one hand, we implied that an FP frame could not contain a byte with value 0xF1 because that matches a Start Flag. On the other hand, a frame may contain a 16-bit actuator/selector value that could certainly include a byte matching 0xF1. Having an End Flag (0xF2) in the body of a frame is a problem for the same reason. The solution we adopt for FP is to define a special encoding for these bytes when they appear within a frame. We reserve a third byte code for this purpose, 0xF0, then encode as follows:

The rule for decoding is that any time we come across an F0 byte, we discard it and OR the following byte with F0. With that, here is the FP transformer:

FRAME_TRANSFORMER

METHOD __FP__ /* Remove byte-stuffings within FP frames */

CODE

{

// Our task is to convert every two-byte sequence of the

// form (F0, XX) to the single byte (F0 or XX). This

// method is used to encode F0, F1, F2.

enum { STUFF_FLAG = 0xF0 };

int iIn, iOut;

// Initialize the arrays. Important: without these lines

// this routine will access random memory and crash.

// We don't know how big the output arrays need to be, but

// we're sure that they won't be bigger than the original,

// so we'll allocate enough memory to cover the worst case.

// We will reallocate later when we know the real size.

ausLowIndex.SetSize(inbytAvailableLayer);

ausHighIndex.SetSize(inbytAvailableLayer);

abVirtualFrame.SetSize(inbytAvailableLayer);

// Process each byte in the frame

for (iIn = iOut = 0; iOut < inbytAvailableLayer; iOut++)

{

// Is this byte a stuff flag?

if ((abytLayer[iOut] == STUFF_FLAG)

&& (iOut != inbytAvailableLayer - 1))

{

// The previous byte was an introducer and this

// one is too. Copy this byte into the frame and

// set the down links so that the byte appears to

// have come from this byte and the previous one.

ausLowIndex[iIn] = (unsigned short) iOut;

ausHighIndex[iIn] = (unsigned short) (iOut + 1);

abVirtualFrame[iIn++] = (BYTE)(abytLayer[++iOut] | 0xF0);

// Set the flag that the frame has been

// transformed. Note that this is an optimization.

// On those frames that have no escape characters,

// output frame is the same as the input frame, so

// no transformation is necessary.

bFrameTransformed = true;

// The previous byte was an introducer and this

// one is too. Copy this byte into the frame and

// set the down links so that the byte appears to

// have come from this byte and the previous one.

ausLowIndex[iIn] = (unsigned short) iOut;

ausHighIndex[iIn] = (unsigned short) (iOut + 1);

abVirtualFrame[iIn++] = (BYTE)(abytLayer[++iOut] | 0xF0);

// Set the flag that the frame has been

// transformed. Note that this is an optimization.

// On those frames that have no escape characters,

// output frame is the same as the input frame, so

// no transformation is necessary.

bFrameTransformed = true;

}

else

{

// Just copy this byte to the new frame

ausLowIndex[iIn] = (unsigned short) iOut;

ausHighIndex[iIn] = (unsigned short) iOut;

abVirtualFrame[iIn++] = abytLayer[iOut];

}

}

// Now we know the correct size of the frame, so if we are

// transforming, then set the size. If this step is not done,

// then the end of the frame will contain garbage.

// If bFrameTransformed is false, then the transformation will

// be skipped completely, so there is no point using any more

// time.

if (bFrameTransformed)

{

ausLowIndex.SetSize(iIn);

ausHighIndex.SetSize(iIn);

bVirtualFrame.SetSize(iIn);

}

}

ENDCODE