void CYSFControl::writeNetwork() { unsigned char data[200U]; unsigned int length = m_network->read(data); if (length == 0U) return; if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE) return; m_networkWatchdog.start(); bool gateway = ::memcmp(data + 4U, m_callsign, YSF_CALLSIGN_LENGTH) == 0; unsigned char n = (data[34U] & 0xFEU) >> 1; bool end = (data[34U] & 0x01U) == 0x01U; if (!m_netTimeoutTimer.isRunning()) { if (end) return; if (::memcmp(data + 14U, " ", YSF_CALLSIGN_LENGTH) != 0) ::memcpy(m_netSource, data + 14U, YSF_CALLSIGN_LENGTH); else ::memcpy(m_netSource, "??????????", YSF_CALLSIGN_LENGTH); if (::memcmp(data + 24U, " ", YSF_CALLSIGN_LENGTH) != 0) ::memcpy(m_netDest, data + 24U, YSF_CALLSIGN_LENGTH); else ::memcpy(m_netDest, "??????????", YSF_CALLSIGN_LENGTH); m_display->writeFusion((char*)m_netSource, (char*)m_netDest, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to %10.10s at %10.10s", m_netSource, m_netDest, data + 4U); m_netTimeoutTimer.start(); m_netPayload.reset(); m_packetTimer.start(); m_elapsed.start(); m_lastFrameValid = false; m_netState = RS_NET_AUDIO; m_netFrames = 0U; m_netLost = 0U; m_netErrs = 0U; m_netBits = 1U; m_netN = 0U; } else { // Check for duplicate frames, if we can if (m_netN == n) return; bool changed = false; if (::memcmp(data + 14U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(m_netSource, "??????????", YSF_CALLSIGN_LENGTH) == 0) { ::memcpy(m_netSource, data + 14U, YSF_CALLSIGN_LENGTH); changed = true; } if (::memcmp(data + 24U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(m_netDest, "??????????", YSF_CALLSIGN_LENGTH) == 0) { ::memcpy(m_netDest, data + 24U, YSF_CALLSIGN_LENGTH); changed = true; } if (changed) { m_display->writeFusion((char*)m_netSource, (char*)m_netDest, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to %10.10s at %10.10s", m_netSource, m_netDest, data + 4U); } } data[33U] = end ? TAG_EOT : TAG_DATA; data[34U] = 0x00U; // bool send = true; CYSFFICH fich; bool valid = fich.decode(data + 35U); if (valid) { unsigned char bn = fich.getBN(); unsigned char bt = fich.getBT(); unsigned char dt = fich.getDT(); unsigned char fn = fich.getFN(); unsigned char ft = fich.getFT(); unsigned char fi = fich.getFI(); fich.setVoIP(true); fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY); fich.encode(data + 35U); m_lastMode = dt; // Set the downlink callsign switch (fi) { case YSF_FI_HEADER: case YSF_FI_TERMINATOR: m_netPayload.processHeaderData(data + 35U); break; case YSF_FI_COMMUNICATIONS: switch (dt) { case YSF_DT_VD_MODE1: { m_netPayload.processVDMode1Data(data + 35U, fn, gateway); unsigned int errors = m_netPayload.processVDMode1Audio(data + 35U); // send = insertSilence(data + 33U, n); // if (send) { m_netErrs += errors; m_netBits += 235U; LogDebug("YSF, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", n, errors, float(errors) / 2.35F); // } } break; case YSF_DT_VD_MODE2: { m_netPayload.processVDMode2Data(data + 35U, fn, gateway); unsigned int errors = m_netPayload.processVDMode2Audio(data + 35U); // send = insertSilence(data + 33U, n); // if (send) { m_netErrs += errors; m_netBits += 135U; LogDebug("YSF, V/D Mode 2, seq %u, Repetition FEC %u/135 (%.1f%%)", n, errors, float(errors) / 1.35F); // } } break; case YSF_DT_DATA_FR_MODE: LogDebug("YSF, Network data FICH B=%u/%u F=%u/%u", bn, bt, fn, ft); m_netPayload.processDataFRModeData(data + 35U, fn, gateway); break; case YSF_DT_VOICE_FR_MODE: if (fn != 0U || ft != 1U) { // The first packet after the header is odd, don't try and regenerate it unsigned int errors = m_netPayload.processVoiceFRModeAudio(data + 35U); // send = insertSilence(data + 33U, n); // if (send) { m_netErrs += errors; m_netBits += 720U; LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); // } } break; default: break; } break; default: break; } } else { // send = insertSilence(data + 33U, n); } // if (send) { writeQueueNet(data + 33U); m_packetTimer.start(); m_netFrames++; m_netN = n; // } if (end) { LogMessage("YSF, received network end of transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); writeEndNet(); } }
void CYSFControl::writeNetwork() { unsigned char data[200U]; unsigned int length = m_network->read(data); if (length == 0U) return; if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE) return; m_networkWatchdog.start(); if (!m_netTimeoutTimer.isRunning()) { if (::memcmp(data + 14U, " ", YSF_CALLSIGN_LENGTH) != 0) ::memcpy(m_netSource, data + 14U, YSF_CALLSIGN_LENGTH); else ::memcpy(m_netSource, "??????????", YSF_CALLSIGN_LENGTH); if (::memcmp(data + 24U, " ", YSF_CALLSIGN_LENGTH) != 0) ::memcpy(m_netDest, data + 24U, YSF_CALLSIGN_LENGTH); else ::memcpy(m_netDest, "??????????", YSF_CALLSIGN_LENGTH); m_display->writeFusion((char*)m_netSource, (char*)m_netDest, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to %10.10s at %10.10s", m_netSource, m_netDest, data + 4U); m_netTimeoutTimer.start(); m_netPayload.reset(); m_netState = RS_NET_AUDIO; m_netFrames = 0U; m_netErrs = 0U; m_netBits = 1U; } else { bool changed = false; if (::memcmp(data + 14U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(m_netSource, "??????????", YSF_CALLSIGN_LENGTH) == 0) { ::memcpy(m_netSource, data + 14U, YSF_CALLSIGN_LENGTH); changed = true; } if (::memcmp(data + 24U, " ", YSF_CALLSIGN_LENGTH) != 0 && ::memcmp(m_netDest, "??????????", YSF_CALLSIGN_LENGTH) == 0) { ::memcpy(m_netDest, data + 24U, YSF_CALLSIGN_LENGTH); changed = true; } if (changed) { m_display->writeFusion((char*)m_netSource, (char*)m_netDest, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to %10.10s at %10.10s", m_netSource, m_netDest, data + 4U); } } m_netFrames++; bool end = data[34U] == 0x01U; data[33U] = end ? TAG_EOT : TAG_DATA; data[34U] = 0x00U; CYSFFICH fich; bool valid = fich.decode(data + 35U); if (valid) { unsigned char dt = fich.getDT(); unsigned char fn = fich.getFN(); unsigned char fi = fich.getFI(); unsigned char ft = fich.getFT(); // Set the downlink callsign switch (fi) { case YSF_FI_HEADER: case YSF_FI_TERMINATOR: m_netPayload.processHeaderData(data + 35U); break; case YSF_FI_COMMUNICATIONS: switch (dt) { case YSF_DT_VD_MODE1: m_netPayload.processVDMode1Data(data + 35U, fn); m_netErrs += m_netPayload.processVDMode1Audio(data + 35U); m_netBits += 235U; break; case YSF_DT_VD_MODE2: m_netPayload.processVDMode2Data(data + 35U, fn); m_netErrs += m_netPayload.processVDMode2Audio(data + 35U); m_netBits += 135U; break; case YSF_DT_DATA_FR_MODE: m_netPayload.processDataFRModeData(data + 35U, fn); break; case YSF_DT_VOICE_FR_MODE: if (fn != 0U || ft != 1U) { // The first packet after the header is odd, don't try and regenerate it m_netErrs += m_netPayload.processVoiceFRModeAudio(data + 35U); m_netBits += 720U; } break; default: break; } break; default: break; } fich.setVoIP(true); fich.setMR(YSF_MR_NOT_BUSY); fich.encode(data + 35U); } writeQueueNet(data + 33U); if (end) { LogMessage("YSF, received network end of transmission, %.1f seconds, BER: %.1f%%", float(m_netFrames) / 10.0F, float(m_netErrs * 100U) / float(m_netBits)); writeEndNet(); } }