/// <summary> /// Processes a 2B "RadioText" frame type 0b00101 /// </summary> /// <param name="frame"></param> private void ProcessFramePayload_RadioTextB(RDSFrame frame) { //Read the header flags bool flagAb = 1 == ((frame.b >> (HEADER_OFFSET - 0)) & 0b0000000000000001); //Get the index and multiply it by 2, as that is the spacing int addressIndex = (frame.b & 0b0000000000001111) * 2; //Check if we should reset if (flagAb != _rtLastAbFlag && addressIndex == 0) { //Clear buffer for (int i = 0; i < rtBuffer.Length; i++) { rtBuffer[i] = (char)0x00; } //Update state _rtLastAbFlag = flagAb; //Send event OnRtBufferCleared?.Invoke(this); } //Write all rtBuffer[addressIndex + 0] = (char)((frame.d >> 8) & 0x00FF); rtBuffer[addressIndex + 1] = (char)((frame.d >> 0) & 0x00FF); //Search this string to see if we reached the end int endIndex = -1; for (int i = addressIndex; i < addressIndex + 4; i++) { if (rtBuffer[i] == (char)0x0A) { endIndex = i; break; } } //Send buffer updated events OnRtBufferUpdated?.Invoke(this, rtBuffer); //Handle ending if we did if (endIndex != -1) { //Convert to string and update state rtText = new string(rtBuffer, 0, endIndex); rtComplete = true; //Send event OnRtTextUpdated?.Invoke(this, rtText); } }
/// <summary> /// Clears out information, but will not stop events. This should be called when a new station is tuned to /// </summary> public void Reset() { //Apply changes rdsSupported = false; piCode = 0; psComplete = false; rtComplete = false; timeComplete = false; psBuffer = CreateEmptyBuffer(8); rtBuffer = CreateEmptyBuffer(64); //Fire events OnPsBufferUpdated?.Invoke(this, psBuffer); OnPsNameUpdated?.Invoke(this, ""); OnRtTextUpdated?.Invoke(this, ""); OnRtBufferUpdated?.Invoke(this, rtBuffer); OnRtBufferCleared?.Invoke(this); OnReset?.Invoke(this); }
/// <summary> /// Processes a 2A "RadioText" frame type 0b00100 /// </summary> /// <param name="frame"></param> private void ProcessFramePayload_RadioTextA(RDSFrame frame) { //Read the header flags bool flagAb = 1 == ((frame.b >> (HEADER_OFFSET - 0)) & 0b0000000000000001); //Get the index and multiply it by 4, as that is the spacing int addressIndex = (frame.b & 0b0000000000001111) * 4; //Check if we should reset if (flagAb != _rtLastAbFlag && addressIndex == 0) { //Clear buffer for (int i = 0; i < rtBuffer.Length; i++) { rtBuffer[i] = (char)0x00; } //Update state _rtLastAbFlag = flagAb; //Send event OnRtBufferCleared?.Invoke(this); } //Write all rtBuffer[addressIndex + 0] = (char)((frame.c >> 8) & 0x00FF); rtBuffer[addressIndex + 1] = (char)((frame.c >> 0) & 0x00FF); rtBuffer[addressIndex + 2] = (char)((frame.d >> 8) & 0x00FF); rtBuffer[addressIndex + 3] = (char)((frame.d >> 0) & 0x00FF); //Search this string to see if we reached the end int endIndex = -1; for (int i = addressIndex; i < addressIndex + 4; i++) { //Official spec claims that the character 0x0A should be used to indicate the end, but some stations in my area don't do that. //We also check \r for this reason. Cumulus Media stations are using \r instead. if (rtBuffer[i] == (char)0x0A || rtBuffer[i] == '\r') { endIndex = i; break; } } //Send buffer updated events OnRtBufferUpdated?.Invoke(this, rtBuffer); //Handle ending if we did if (endIndex != -1) { //Make sure this is really the end. We should have no null characters up to this point for (int i = 0; i < endIndex; i++) { if (rtBuffer[i] == (char)0x00) { return; } } //Convert to string and update state rtText = new string(rtBuffer, 0, endIndex); rtComplete = true; //Send event OnRtTextUpdated?.Invoke(this, rtText); } }