Looking at UECP Stream Encoding

Getting the UECP stream into shape

Once the UECP data has been set up it has to be post-treated before sending on.

Encoding the UECP Stream

There are literally 100's of C# NET Serial Port libraries on the web so there is no need to to deal with my implementation since there is nothing special in way it has been done.

However there are some UECP specific parts. Once the UECP frame has been set up it has to be passed through a stuffing and CRC calculation. This I show here:

static public Boolean RDS_Stuff(ref Byte[] buffer, Byte first, Byte last, ref Byte length)
{
    //  Scan the frame and byte stuff
    UInt16 count = 0;
    Byte b = 0x00;
    Byte[] send = new Byte[512];
    send[0] = buffer[0];
    //  first will be the start byte
    Byte position = first;
    //  256 is the maximum frame length. There are 8 byte for the header and tail
    //  so maximum position is 253 to allow margin
    for (count = first; ((count <= last) && (count < buffer.Length)); count++)
    {
        b = buffer[count];
        switch (b)
        {
            case REPLACE_STUFF_FF:
                send[position++] = STUFFING_IDENTIFIER;
                send[position++] = STUFF_FF;
                break;
            case REPLACE_STUFF_FE:
                send[position++] = STUFFING_IDENTIFIER;
                send[position++] = STUFF_FE;
                break;
            case REPLACE_STUFF_FD:
                send[position++] = STUFFING_IDENTIFIER;
                send[position++] = STUFF_FD;
                break;
            default:
                send[position++] = b;
                break;
        }
    }
    //  position will now point to the last byte
    send[position] = RDS_STOP_BYTE;
    length = (Byte)(position + 1);
    if ((position > 253) || (length > buffer.Length)) return false;
    //  Transfer send back into buffer, provided length <= buffer.Length
    for (count = 0; count < length; count++)
        buffer[count] = send[count];
    return true;
}

buffer has the complete incoming stream

first is the initial byte position of the stream to be stuffed

last is the last byte position to be considered for stuffing

length is the maximum length of the result buffer available. When there is stuufing this must be more than the incoming stream length and within the maximum limits.

Likewise the de-stuffing for the frame replies:

private void De_Stuff(ref Byte[] buffer)
{
    //  Scan the buffer and return in a new exact length buffer
    Int16 i = 0;
    Byte position = 0;
    Boolean bEnd = false;
    for (i = 0; (i < buffer.Length) & (bEnd == false); i++)
    {
        if (buffer[i] == STUFFING_IDENTIFIER)
        {
            i++;    //  Move to next element
            if (buffer[i] == STUFF_FF) buffer[position++] = REPLACE_STUFF_FF;
            else if (buffer[i] == STUFF_FE) buffer[position++] = REPLACE_STUFF_FE;
            else if (buffer[i] == STUFF_FD) buffer[position++] = REPLACE_STUFF_FD;
        }
        else buffer[position++] = buffer[i];
    }
}

Then there is the CRC calculation:

static public UInt16 RDS_CRC_CCITT16(Byte[] buffer, Byte first, Byte last)
{
    //  Takes the chain of bytes in buffer from first to last inclusive
    Byte i = 0;
    UInt16 crc = 0xFFFF;  // Initialise for CCITT-16
    //  Scan buffer
    for (i = first; i <= last; i++)
    {
        crc = (UInt16)(((crc >> 8) & 0x00FF) | ((crc << 8) & 0xFF00));
        crc ^= (UInt16)buffer[i];
        crc ^= (UInt16)((crc & 0x00FF) >> 4);
        crc ^= (UInt16)((crc << 8) << 4);
        crc ^= (UInt16)(((crc & 0x00FF) << 4) << 1);
    }
    return crc;
}