The UECP communication to the RDS devices is no ordinary free format asynchronous stream. The format and commands are defined by the RDS specification.
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:
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.