Looking at how to Construct the UECP Stream

Getting the UECP stream constructed

The UECP communication to the RDS devices is no ordinary free format asynchronous stream. The format and commands are defined by the RDS specification.

Construct the UECP Stream

Well what does the CISC CPU wait for? Answer: a change in RDS data, the reception of UECP data is what we are going to look into here. First the UECP stream has to be collected:

RDS serial flow chart

All the frame can be pre-defined. Here the PI frame is get and set by different functions:

GET:    MEC MEL DSN PSN     MEC = 0x17
SET:    MEC DSN PSN PI PI   MEC = 0x01
private Boolean Get_RDS_PI(UInt16 pi, Byte psn, Byte dsn)
{
    Byte[] buffer = new Byte[256];   //  The command buffer
    Byte buffer_length = 0;
    //  Get information with MEC
    Byte[] cmd = { 0x02, 0x17, 0x03, 0x01, 0x00, 0x00, 0x0D };
    //  Place incoming information into the correct command bytes
        cmd[4] = dsn;
        cmd[5] = psn;
        if (Trunk.WriteAndReadAttachedEquipment(cmd, (Byte)cmd.Length, ref buffer, ref buffer_length) == true)
        {
            //  <MEC_REQUEST><3><MEC_PI><dsn><psn><upper PI><lower PI>
            if (buffer_length >= 7)
            {
                pi = (UInt16)(((UInt16)buffer[5] << 8) & 0xFF00);
                pi |= (UInt16)((UInt16)buffer[6] & 0x00FF);
                iLastErrorNumber = RDSComm.RDSCommandAnswerCorrect;
                sLastErrorString = "Equipment answer sufficient";
                return true;
            }
        }
        iLastErrorNumber = RDSComm.RDSAnswerError;
        sLastErrorString = "Equipment RDS PI not correct";
        return false;
}

Each UECP frame is padded by a STX to start and CR to finish. These markers are used as indicators to add the START and STOP parts of the variable length UECP frame. Other information frames are created in the same way, different MEC, different payload.

private Boolean Set_RDS_PI(ref UInt16 pi, Byte psn, Byte dsn)
{
    Byte[] buffer = new Byte[256];   //  The command buffer
    Byte buffer_length = 0;
    //  Set the information with MEC
    //  <MEC_PI><DSN><PSN><upper PI><lower PI>
    Byte[] cmd = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D };
    //  Place incoming information into the correct command bytes
        cmd[2] = psn;
        cmd[3] = dsn;
        cmd[4] = (Byte)((pi >> 8) & 0x00FF);
        cmd[5] = (Byte)(pi & 0x00FF);
        if (Trunk.WriteAndReadAttachedEquipment(cmd, (Byte)cmd.Length, ref buffer, ref buffer_length) == true)
        {
            //  Should have changed so do next one, check response
            //  The correct response is <0x18><0x00><sequence_number>
            if (buffer_length > 2)
            {
                if (buffer[1] == 0x00)
                {
                    iLastErrorNumber = RDSComm.RDSCommandAnswerCorrect;
                    sLastErrorString = "Equipment answer sufficient";
                    return true;
                }
            }
        }
    }
    iLastErrorNumber = RDSComm.RDSAnswerError;
    sLastErrorString = "Equipment RDS PI not correct";
    return false;
}

The underlying trunk handler will have checked the crc and sequence number before raising a "true" reply.