void CDStarControl::clock(unsigned int ms) { if (m_network != NULL) writeNetwork(); m_ackTimer.clock(ms); if (m_ackTimer.isRunning() && m_ackTimer.hasExpired()) { sendAck(); m_ackTimer.stop(); } m_holdoffTimer.clock(ms); if (m_holdoffTimer.isRunning() && m_holdoffTimer.hasExpired()) m_holdoffTimer.stop(); m_timeoutTimer.clock(ms); if (m_state == RS_RELAYING_NETWORK_AUDIO) { m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { // We're received the header haven't we? m_frames += 1U; if (m_bits == 0U) m_bits = 1U; LogMessage("D-Star, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits)); m_timeoutTimer.stop(); writeEndOfTransmission(); #if defined(DUMP_DSTAR) closeFile(); #endif } } if (m_state == RS_RELAYING_NETWORK_AUDIO) { m_packetTimer.clock(ms); if (m_packetTimer.isRunning() && m_packetTimer.hasExpired()) { unsigned int frames = m_elapsed.elapsed() / DSTAR_FRAME_TIME; if (frames > m_frames) { unsigned int count = frames - m_frames; if (count > 3U) { LogMessage("D-Star, lost audio for 300ms filling in, %u %u", frames, m_frames); insertSilence(count - 1U); } } m_packetTimer.start(); } } }
void CYSFControl::clock(unsigned int ms) { if (m_network != NULL) writeNetwork(); m_holdoffTimer.clock(ms); if (m_holdoffTimer.isRunning() && m_holdoffTimer.hasExpired()) m_holdoffTimer.stop(); m_rfTimeoutTimer.clock(ms); m_netTimeoutTimer.clock(ms); if (m_netState == RS_NET_AUDIO) { m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { LogMessage("YSF, network watchdog has expired, %.1f seconds, BER: %.1f%%", float(m_netFrames) / 10.0F, float(m_netErrs * 100U) / float(m_netBits)); writeEndNet(); } } }
void CP25Control::clock(unsigned int ms) { if (m_network != NULL) writeNetwork(); m_rfTimeout.clock(ms); m_netTimeout.clock(ms); if (m_netState == RS_NET_AUDIO) { m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { LogMessage("P25, network watchdog has expired, %.1f seconds, %u%% packet loss", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); m_display->clearP25(); m_networkWatchdog.stop(); m_netState = RS_NET_IDLE; m_netData.reset(); m_netTimeout.stop(); } } }
void CYSFControl::clock(unsigned int ms) { if (m_network != NULL) writeNetwork(); m_rfTimeoutTimer.clock(ms); m_netTimeoutTimer.clock(ms); if (m_netState == RS_NET_AUDIO) { m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { LogMessage("YSF, network watchdog has expired, %.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(); } } /* if (m_netState == RS_NET_AUDIO) { m_packetTimer.clock(ms); if (m_packetTimer.isRunning() && m_packetTimer.hasExpired()) { unsigned int elapsed = m_elapsed.elapsed(); unsigned int frames = elapsed / YSF_FRAME_TIME; if (frames > m_netFrames) { unsigned int count = frames - m_netFrames; if (count > 2U) { LogDebug("YSF, lost audio for 200ms filling in, elapsed: %ums, expected: %u, received: %u", elapsed, frames, m_netFrames); insertSilence(count - 1U); } } m_packetTimer.start(); } } */ }
int main() { neural::Network net; char inFile[] = "net1.json"; char outFile[] = "test1.json"; readNetwork(inFile, &net); writeNetwork(outFile, &net); /* std::vector<double> inputValues; //Values to train neural network input with forward-propagation std::vector<double> targetValues; //Values to train neural network output with back-propagation std::vector<double> resultValues; //Holds output from neural net //Train network myNet.feedForward(inputValues); //Input on input training data myNet.backPropagation(targetValues); //Train on expected output with backpropagation myNet.getResults(resultValues); */ return 0; }
bool CYSFControl::writeModem(unsigned char *data, unsigned int len) { assert(data != NULL); unsigned char type = data[0U]; if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) { LogMessage("YSF, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } if (type == TAG_LOST) return false; CYSFFICH fich; bool valid = fich.decode(data + 2U); if (valid && m_rfState == RS_RF_LISTENING) { unsigned char fi = fich.getFI(); if (fi == YSF_FI_TERMINATOR) return false; m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; m_rfTimeoutTimer.start(); m_rfPayload.reset(); m_rfState = RS_RF_AUDIO; #if defined(DUMP_YSF) openFile(); #endif } if (m_rfState != RS_RF_AUDIO) return false; if (valid) m_lastMR = fich.getMR(); // Stop repeater packets coming through, unless we're acting as a remote gateway if (m_remoteGateway) { if (m_lastMR != YSF_MR_BUSY) return false; } else { if (m_lastMR == YSF_MR_BUSY) return false; } unsigned char fi = fich.getFI(); if (valid && fi == YSF_FI_HEADER) { CSync::addYSFSync(data + 2U); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); valid = m_rfPayload.processHeaderData(data + 2U); if (valid) m_rfSource = m_rfPayload.getSource(); unsigned char cm = fich.getCM(); if (cm == YSF_CM_GROUP) { m_rfDest = (unsigned char*)"ALL "; } else { if (valid) m_rfDest = m_rfPayload.getDest(); } if (m_rfSource != NULL && m_rfDest != NULL) { m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF header from %10.10s to %10.10s", m_rfSource, m_rfDest); } else if (m_rfSource == NULL && m_rfDest != NULL) { m_display->writeFusion("??????????", (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF header from ?????????? to %10.10s", m_rfDest); } else if (m_rfSource != NULL && m_rfDest == NULL) { m_display->writeFusion((char*)m_rfSource, "??????????", "R", " "); LogMessage("YSF, received RF header from %10.10s to ??????????", m_rfSource); } else { m_display->writeFusion("??????????", "??????????", "R", " "); LogMessage("YSF, received RF header from ?????????? to ??????????"); } data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data, m_rfFrames % 128U); #if defined(DUMP_YSF) writeFile(data + 2U); #endif if (m_duplex) { fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } m_rfFrames++; } else if (valid && fi == YSF_FI_TERMINATOR) { CSync::addYSFSync(data + 2U); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); m_rfPayload.processHeaderData(data + 2U); data[0U] = TAG_EOT; data[1U] = 0x00U; writeNetwork(data, m_rfFrames % 128U); #if defined(DUMP_YSF) writeFile(data + 2U); #endif if (m_duplex) { fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } m_rfFrames++; LogMessage("YSF, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } else if (valid) { CSync::addYSFSync(data + 2U); unsigned char bn = fich.getBN(); unsigned char bt = fich.getBT(); unsigned char fn = fich.getFN(); unsigned char ft = fich.getFT(); unsigned char dt = fich.getDT(); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); switch (dt) { case YSF_DT_VD_MODE1: { valid = m_rfPayload.processVDMode1Data(data + 2U, fn); unsigned int errors = m_rfPayload.processVDMode1Audio(data + 2U); m_rfErrs += errors; m_rfBits += 235U; LogDebug("YSF, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 2.35F); } break; case YSF_DT_VD_MODE2: { valid = m_rfPayload.processVDMode2Data(data + 2U, fn); unsigned int errors = m_rfPayload.processVDMode2Audio(data + 2U); m_rfErrs += errors; m_rfBits += 135U; LogDebug("YSF, V/D Mode 2, seq %u, Repetition FEC %u/135 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 1.35F); } break; case YSF_DT_DATA_FR_MODE: LogDebug("YSF, RF data FICH B=%u/%u F=%u/%u", bn, bt, fn, ft); valid = m_rfPayload.processDataFRModeData(data + 2U, 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 unsigned int errors = m_rfPayload.processVoiceFRModeAudio(data + 2U); m_rfErrs += errors; m_rfBits += 720U; LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); } valid = false; break; default: break; } bool change = false; if (m_rfDest == NULL) { unsigned char cm = fich.getCM(); if (cm == YSF_CM_GROUP) { m_rfDest = (unsigned char*)"ALL "; change = true; } else if (valid) { m_rfDest = m_rfPayload.getDest(); if (m_rfDest != NULL) change = true; } } if (valid && m_rfSource == NULL) { m_rfSource = m_rfPayload.getSource(); if (m_rfSource != NULL) change = true; } if (change) { if (m_rfSource != NULL && m_rfDest != NULL) { m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF data from %10.10s to %10.10s", m_rfSource, m_rfDest); } if (m_rfSource != NULL && m_rfDest == NULL) { m_display->writeFusion((char*)m_rfSource, "??????????", "R", " "); LogMessage("YSF, received RF data from %10.10s to ??????????", m_rfSource); } if (m_rfSource == NULL && m_rfDest != NULL) { m_display->writeFusion("??????????", (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF data from ?????????? to %10.10s", m_rfDest); } } data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data, m_rfFrames % 128U); if (m_duplex) { fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } #if defined(DUMP_YSF) writeFile(data + 2U); #endif m_rfFrames++; } else { CSync::addYSFSync(data + 2U); data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data, m_rfFrames % 128U); if (m_duplex) writeQueueRF(data); #if defined(DUMP_YSF) writeFile(data + 2U); #endif m_rfFrames++; } return true; }
void CDMRSlot::writeModem(unsigned char *data) { if (data[0U] == TAG_LOST && m_state == SS_RELAYING_RF) { LogMessage("DMR Slot %u, transmission lost", m_slotNo); writeEndOfTransmission(); return; } if (data[0U] == TAG_LOST && m_state == SS_LATE_ENTRY) { m_state = SS_LISTENING; return; } if (m_state == SS_RELAYING_NETWORK) return; bool dataSync = (data[1U] & DMR_SYNC_DATA) == DMR_SYNC_DATA; bool audioSync = (data[1U] & DMR_SYNC_AUDIO) == DMR_SYNC_AUDIO; if (dataSync) { CSlotType slotType; slotType.putData(data + 2U); unsigned char colorCode = slotType.getColorCode(); unsigned char dataType = slotType.getDataType(); if (colorCode != m_colorCode) return; if (dataType == DT_VOICE_LC_HEADER) { if (m_state != SS_RELAYING_RF) { CFullLC fullLC; m_lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER); if (m_lc == NULL) { LogMessage("DMR Slot %u: unable to decode the LC", m_slotNo); return; } // Regenerate the LC fullLC.encode(*m_lc, data + 2U, DT_VOICE_LC_HEADER); // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; m_n = 0U; m_networkWatchdog.stop(); m_timeoutTimer.start(); m_seqNo = 0U; for (unsigned i = 0U; i < 3U; i++) { writeNetwork(data, DT_VOICE_LC_HEADER); writeRadioQueue(data); } m_state = SS_RELAYING_RF; setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO()); m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId()); LogMessage("DMR Slot %u, received RF header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); } } else if (dataType == DT_VOICE_PI_HEADER) { if (m_state == SS_RELAYING_RF) { // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; m_n = 0U; writeNetwork(data, DT_VOICE_PI_HEADER); writeRadioQueue(data); LogMessage("DMR Slot %u, received PI header", m_slotNo); } else { // Should save the PI header for after we have a valid LC } } else { // Ignore wakeup CSBKs if (dataType == DT_CSBK) { CCSBK csbk(data + 2U); CSBKO csbko = csbk.getCSBKO(); if (csbko == CSBKO_BSDWNACT) return; } if (m_state == SS_RELAYING_RF) { unsigned char end[DMR_FRAME_LENGTH_BYTES + 2U]; // Generate the LC CFullLC fullLC; fullLC.encode(*m_lc, end + 2U, DT_TERMINATOR_WITH_LC); // Generate the Slot Type CSlotType slotType; slotType.setColorCode(m_colorCode); slotType.setDataType(DT_TERMINATOR_WITH_LC); slotType.getData(end + 2U); // Set the Data Sync to be from the BS CDMRSync sync; sync.addSync(end + 2U, DST_BS_DATA); end[0U] = TAG_EOT; end[1U] = 0x00U; writeNetwork(end, DT_TERMINATOR_WITH_LC); writeRadioQueue(end); LogMessage("DMR Slot %u, received RF end of transmission", m_slotNo); // 480ms of idle to space things out for (unsigned int i = 0U; i < 8U; i++) writeRadioQueue(m_idle); writeEndOfTransmission(); if (dataType == DT_TERMINATOR_WITH_LC) return; } // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data, dataType); writeRadioQueue(data); } } else if (audioSync) { if (m_state == SS_RELAYING_RF) { // Convert the Audio Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_AUDIO); unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) ; // AMBE FEC data[0U] = TAG_DATA; data[1U] = 0x00U; m_n = 0U; writeRadioQueue(data); writeNetwork(data, DT_VOICE_SYNC); } else if (m_state == SS_LISTENING) { m_state = SS_LATE_ENTRY; } } else { if (m_state == SS_RELAYING_RF) { // Regenerate the EMB CEMB emb; emb.putData(data + 2U); emb.setColorCode(m_colorCode); emb.getData(data + 2U); unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) ; // AMBE FEC data[0U] = TAG_DATA; data[1U] = 0x00U; m_n++; writeRadioQueue(data); writeNetwork(data, DT_VOICE); } else if (m_state == SS_LATE_ENTRY) { // If we haven't received an LC yet, then be strict on the color code CEMB emb; emb.putData(data + 2U); unsigned char colorCode = emb.getColorCode(); if (colorCode != m_colorCode) return; m_lc = m_embeddedLC.addData(data + 2U, emb.getLCSS()); if (m_lc != NULL) { // Create a dummy start frame to replace the received frame unsigned char start[DMR_FRAME_LENGTH_BYTES + 2U]; CDMRSync sync; sync.addSync(start + 2U, DST_BS_DATA); CFullLC fullLC; fullLC.encode(*m_lc, start + 2U, DT_VOICE_LC_HEADER); CSlotType slotType; slotType.setColorCode(m_colorCode); slotType.setDataType(DT_VOICE_LC_HEADER); slotType.getData(start + 2U); start[0U] = TAG_DATA; start[1U] = 0x00U; m_n = 0U; m_networkWatchdog.stop(); m_timeoutTimer.start(); m_seqNo = 0U; for (unsigned int i = 0U; i < 3U; i++) { writeNetwork(start, DT_VOICE_LC_HEADER); writeRadioQueue(start); } // Send the original audio frame out unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) ; // AMBE FEC data[0U] = TAG_DATA; data[1U] = 0x00U; m_n++; writeRadioQueue(data); writeNetwork(data, DT_VOICE); m_state = SS_RELAYING_RF; setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO()); m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId()); LogMessage("DMR Slot %u, received RF late entry from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); } } } }
bool CYSFControl::writeModem(unsigned char *data) { assert(data != NULL); unsigned char type = data[0U]; if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) { LogMessage("YSF, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } if (type == TAG_LOST) return false; CYSFFICH fich; bool valid = fich.decode(data + 2U); if (valid && m_rfState == RS_RF_LISTENING) { unsigned char fi = fich.getFI(); if (fi == YSF_FI_TERMINATOR) return false; m_holdoffTimer.stop(); m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; m_rfTimeoutTimer.start(); m_rfPayload.reset(); m_rfState = RS_RF_AUDIO; #if defined(DUMP_YSF) openFile(); #endif } if (m_rfState != RS_RF_AUDIO) return false; unsigned char fi = fich.getFI(); if (valid && fi == YSF_FI_HEADER) { CSync::addYSFSync(data + 2U); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); m_rfFrames++; valid = m_rfPayload.processHeaderData(data + 2U); if (valid) m_rfSource = m_rfPayload.getSource(); unsigned char cm = fich.getCM(); if (cm == YSF_CM_GROUP) { m_rfDest = (unsigned char*)"ALL "; } else { if (valid) m_rfDest = m_rfPayload.getDest(); } if (m_rfSource != NULL && m_rfDest != NULL) { m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF header from %10.10s to %10.10s", m_rfSource, m_rfDest); } else if (m_rfSource == NULL && m_rfDest != NULL) { m_display->writeFusion("??????????", (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF header from ?????????? to %10.10s", m_rfDest); } else if (m_rfSource != NULL && m_rfDest == NULL) { m_display->writeFusion((char*)m_rfSource, "??????????", "R", " "); LogMessage("YSF, received RF header from %10.10s to ??????????", m_rfSource); } else { m_display->writeFusion("??????????", "??????????", "R", " "); LogMessage("YSF, received RF header from ?????????? to ??????????"); } data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data); #if defined(DUMP_YSF) writeFile(data + 2U); #endif if (m_duplex) { fich.setMR(YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } } else if (valid && fi == YSF_FI_TERMINATOR) { CSync::addYSFSync(data + 2U); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); m_rfFrames++; m_rfPayload.processHeaderData(data + 2U); data[0U] = TAG_EOT; data[1U] = 0x00U; writeNetwork(data); #if defined(DUMP_YSF) writeFile(data + 2U); #endif if (m_duplex) { fich.setMR(YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } LogMessage("YSF, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } else if (valid) { CSync::addYSFSync(data + 2U); unsigned char fn = fich.getFN(); unsigned char ft = fich.getFT(); unsigned char dt = fich.getDT(); // LogDebug("YSF, FICH: FI: %u, DT: %u, FN: %u, FT: %u", fich.getFI(), fich.getDT(), fich.getFN(), fich.getFT()); m_rfFrames++; switch (dt) { case YSF_DT_VD_MODE1: valid = m_rfPayload.processVDMode1Data(data + 2U, fn); m_rfErrs += m_rfPayload.processVDMode1Audio(data + 2U); m_rfBits += 235U; break; case YSF_DT_VD_MODE2: valid = m_rfPayload.processVDMode2Data(data + 2U, fn); m_rfErrs += m_rfPayload.processVDMode2Audio(data + 2U); m_rfBits += 135U; break; case YSF_DT_DATA_FR_MODE: valid = m_rfPayload.processDataFRModeData(data + 2U, 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_rfErrs += m_rfPayload.processVoiceFRModeAudio(data + 2U); m_rfBits += 720U; } valid = false; break; default: break; } bool change = false; if (m_rfDest == NULL) { unsigned char cm = fich.getCM(); if (cm == YSF_CM_GROUP) { m_rfDest = (unsigned char*)"ALL "; change = true; } else if (valid) { m_rfDest = m_rfPayload.getDest(); if (m_rfDest != NULL) change = true; } } if (valid && m_rfSource == NULL) { m_rfSource = m_rfPayload.getSource(); if (m_rfSource != NULL) change = true; } if (change) { if (m_rfSource != NULL && m_rfDest != NULL) { m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF data from %10.10s to %10.10s", m_rfSource, m_rfDest); } if (m_rfSource != NULL && m_rfDest == NULL) { m_display->writeFusion((char*)m_rfSource, "??????????", "R", " "); LogMessage("YSF, received RF data from %10.10s to ??????????", m_rfSource); } if (m_rfSource == NULL && m_rfDest != NULL) { m_display->writeFusion("??????????", (char*)m_rfDest, "R", " "); LogMessage("YSF, received RF data from ?????????? to %10.10s", m_rfDest); } } data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data); if (m_duplex) { fich.setMR(YSF_MR_BUSY); fich.encode(data + 2U); writeQueueRF(data); } #if defined(DUMP_YSF) writeFile(data + 2U); #endif } else { CSync::addYSFSync(data + 2U); m_rfFrames++; data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data); if (m_duplex) writeQueueRF(data); #if defined(DUMP_YSF) writeFile(data + 2U); #endif } return true; }
void CDMRSlot::writeModem(unsigned char *data) { if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) { LogMessage("DMR Slot %u, transmission lost, BER: %u%%", m_slotNo, (m_errs * 100U) / m_bits); writeEndOfTransmission(); return; } if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_DATA) { LogMessage("DMR Slot %u, transmission lost", m_slotNo); writeEndOfTransmission(); return; } if (data[0U] == TAG_LOST && m_state == RS_LATE_ENTRY) { m_state = RS_LISTENING; return; } if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA) return; bool dataSync = (data[1U] & DMR_SYNC_DATA) == DMR_SYNC_DATA; bool audioSync = (data[1U] & DMR_SYNC_AUDIO) == DMR_SYNC_AUDIO; if (dataSync) { CSlotType slotType; slotType.putData(data + 2U); unsigned char dataType = slotType.getDataType(); if (dataType == DT_VOICE_LC_HEADER) { if (m_state == RS_RELAYING_RF_AUDIO) return; CFullLC fullLC; m_lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER); if (m_lc == NULL) { LogMessage("DMR Slot %u: unable to decode the LC", m_slotNo); return; } // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; m_networkWatchdog.stop(); m_timeoutTimer.start(); m_seqNo = 0U; m_n = 0U; m_bits = 1U; m_errs = 0U; // Put a small delay into starting retransmission writeQueue(m_idle); for (unsigned i = 0U; i < 3U; i++) { writeNetwork(data, DT_VOICE_LC_HEADER); writeQueue(data); } m_state = RS_RELAYING_RF_AUDIO; setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO()); m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId()); LogMessage("DMR Slot %u, received RF voice header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); } else if (dataType == DT_VOICE_PI_HEADER) { if (m_state != RS_RELAYING_RF_AUDIO) return; // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; m_n = 0U; writeNetwork(data, DT_VOICE_PI_HEADER); writeQueue(data); } else if (dataType == DT_TERMINATOR_WITH_LC) { if (m_state != RS_RELAYING_RF_AUDIO) return; // Regenerate the Slot Type slotType.getData(data + 2U); // Set the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_EOT; data[1U] = 0x00U; writeNetwork(data, DT_TERMINATOR_WITH_LC); writeQueue(data); LogMessage("DMR Slot %u, received RF end of voice transmission, BER: %u%%", m_slotNo, (m_errs * 100U) / m_bits); // 480ms of idle to space things out for (unsigned int i = 0U; i < 8U; i++) writeQueue(m_idle); writeEndOfTransmission(); } else if (dataType == DT_DATA_HEADER) { if (m_state == RS_RELAYING_RF_DATA) return; // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; m_networkWatchdog.stop(); m_seqNo = 0U; m_n = 0U; // Put a small delay into starting retransmission writeQueue(m_idle); for (unsigned i = 0U; i < 3U; i++) { writeNetwork(data, DT_DATA_HEADER); writeQueue(data); } m_state = RS_RELAYING_RF_DATA; // setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO()); // m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId()); // LogMessage("DMR Slot %u, received RF data header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); LogMessage("DMR Slot %u, received RF data header", m_slotNo); } else { // Regenerate the Slot Type slotType.getData(data + 2U); // Convert the Data Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_DATA); data[0U] = TAG_DATA; data[1U] = 0x00U; writeNetwork(data, dataType); writeQueue(data); } } else if (audioSync) { if (m_state == RS_RELAYING_RF_AUDIO) { // Convert the Audio Sync to be from the BS CDMRSync sync; sync.addSync(data + 2U, DST_BS_AUDIO); unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) m_errs += m_fec.regenerateDMR(data + 2U); m_bits += 216U; data[0U] = TAG_DATA; data[1U] = 0x00U; m_n = 0U; writeQueue(data); writeNetwork(data, DT_VOICE_SYNC); } else if (m_state == RS_LISTENING) { m_state = RS_LATE_ENTRY; } } else { CEMB emb; emb.putData(data + 2U); if (m_state == RS_RELAYING_RF_AUDIO) { // Regenerate the EMB emb.setColorCode(m_colorCode); emb.getData(data + 2U); unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) m_errs += m_fec.regenerateDMR(data + 2U); m_bits += 216U; data[0U] = TAG_DATA; data[1U] = 0x00U; m_n++; writeQueue(data); writeNetwork(data, DT_VOICE); } else if (m_state == RS_LATE_ENTRY) { // If we haven't received an LC yet, then be strict on the color code unsigned char colorCode = emb.getColorCode(); if (colorCode != m_colorCode) return; m_lc = m_embeddedLC.addData(data + 2U, emb.getLCSS()); if (m_lc != NULL) { // Create a dummy start frame to replace the received frame unsigned char start[DMR_FRAME_LENGTH_BYTES + 2U]; CDMRSync sync; sync.addSync(start + 2U, DST_BS_DATA); CFullLC fullLC; fullLC.encode(*m_lc, start + 2U, DT_VOICE_LC_HEADER); CSlotType slotType; slotType.setColorCode(m_colorCode); slotType.setDataType(DT_VOICE_LC_HEADER); slotType.getData(start + 2U); start[0U] = TAG_DATA; start[1U] = 0x00U; m_networkWatchdog.stop(); m_timeoutTimer.start(); m_seqNo = 0U; m_n = 0U; m_bits = 1U; m_errs = 0U; for (unsigned int i = 0U; i < 3U; i++) { writeNetwork(start, DT_VOICE_LC_HEADER); writeQueue(start); } // Regenerate the EMB emb.getData(data + 2U); // Send the original audio frame out unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) m_errs += m_fec.regenerateDMR(data + 2U); m_bits += 216U; data[0U] = TAG_DATA; data[1U] = 0x00U; m_n++; writeQueue(data); writeNetwork(data, DT_VOICE); m_state = RS_RELAYING_RF_AUDIO; setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO()); m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId()); LogMessage("DMR Slot %u, received RF late entry from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); } } } }
bool CP25Control::writeModem(unsigned char* data, unsigned int len) { assert(data != NULL); bool sync = data[1U] == 0x01U; if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) { if (m_rssi != 0U) LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); else LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); if (m_netState == RS_NET_IDLE) m_display->clearP25(); writeNetwork(m_rfLDU, m_lastDUID, true); writeNetwork(data + 2U, P25_DUID_TERM, true); m_rfState = RS_RF_LISTENING; m_rfTimeout.stop(); m_rfData.reset(); #if defined(DUMP_P25) closeFile(); #endif return false; } if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) { if (m_netState == RS_NET_IDLE) m_display->clearP25(); m_rfState = RS_RF_LISTENING; m_rfPDUCount = 0U; m_rfPDUBits = 0U; #if defined(DUMP_P25) closeFile(); #endif return false; } if (data[0U] == TAG_LOST) { m_rfState = RS_RF_LISTENING; return false; } if (!sync && m_rfState == RS_RF_LISTENING) return false; // Decode the NID bool valid = m_nid.decode(data + 2U); if (m_rfState == RS_RF_LISTENING && !valid) return false; unsigned char duid = m_nid.getDUID(); if (!valid) { switch (m_lastDUID) { case P25_DUID_HEADER: case P25_DUID_LDU2: duid = P25_DUID_LDU1; break; case P25_DUID_LDU1: duid = P25_DUID_LDU2; break; case P25_DUID_PDU: duid = P25_DUID_PDU; break; case P25_DUID_TSDU: duid = P25_DUID_TSDU; break; default: break; } } // Have we got RSSI bytes on the end of a P25 LDU? if (len == (P25_LDU_FRAME_LENGTH_BYTES + 4U)) { uint16_t raw = 0U; raw |= (data[218U] << 8) & 0xFF00U; raw |= (data[219U] << 0) & 0x00FFU; // Convert the raw RSSI to dBm int rssi = m_rssiMapper->interpolate(raw); if (rssi != 0) LogDebug("P25, raw RSSI: %u, reported RSSI: %d dBm", raw, rssi); // RSSI is always reported as positive m_rssi = (rssi >= 0) ? rssi : -rssi; if (m_rssi > m_minRSSI) m_minRSSI = m_rssi; if (m_rssi < m_maxRSSI) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; m_rssiCount++; } if (duid == P25_DUID_LDU1) { if (m_rfState == RS_RF_LISTENING) { m_rfData.reset(); bool ret = m_rfData.decodeLDU1(data + 2U); if (!ret) { m_lastDUID = duid; return false; } unsigned int srcId = m_rfData.getSrcId(); if (m_selfOnly) { if (m_id > 99999999U) { // Check that the Config DMR-ID is bigger than 8 digits if (srcId != m_id / 100U) return false; } else if (m_id > 9999999U) { // Check that the Config DMR-ID is bigger than 7 digits if (srcId != m_id / 10U) return false; } else if (srcId != m_id) { // All other cases return false; } } if (!m_uidOverride) { bool found = m_lookup->exists(srcId); if (!found) return false; } bool grp = m_rfData.getLCF() == P25_LCF_GROUP; unsigned int dstId = m_rfData.getDstId(); std::string source = m_lookup->find(srcId); LogMessage("P25, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); m_display->writeP25(source.c_str(), grp, dstId, "R"); m_rfState = RS_RF_AUDIO; m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; m_rssiCount = 1U; createRFHeader(); writeNetwork(data + 2U, P25_DUID_HEADER, false); } else if (m_rfState == RS_RF_AUDIO) { writeNetwork(m_rfLDU, m_lastDUID, false); } if (m_rfState == RS_RF_AUDIO) { // Regenerate Sync CSync::addP25Sync(data + 2U); // Regenerate NID m_nid.encode(data + 2U, P25_DUID_LDU1); // Regenerate LDU1 Data m_rfData.encodeLDU1(data + 2U); // Regenerate the Low Speed Data m_rfLSD.process(data + 2U); // Regenerate Audio unsigned int errors = m_audio.process(data + 2U); LogDebug("P25, LDU1 audio, errs: %u/1233 (%.1f%%)", errors, float(errors) / 12.33F); m_display->writeP25BER(float(errors) / 12.33F); m_rfBits += 1233U; m_rfErrs += errors; m_rfFrames++; m_lastDUID = duid; // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); #if defined(DUMP_P25) writeFile(data + 2U, len - 2U); #endif ::memcpy(m_rfLDU, data + 2U, P25_LDU_FRAME_LENGTH_BYTES); if (m_duplex) { data[0U] = TAG_DATA; data[1U] = 0x00U; writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U); } m_display->writeP25RSSI(m_rssi); return true; } } else if (duid == P25_DUID_LDU2) { if (m_rfState == RS_RF_AUDIO) { writeNetwork(m_rfLDU, m_lastDUID, false); // Regenerate Sync CSync::addP25Sync(data + 2U); // Regenerate NID m_nid.encode(data + 2U, P25_DUID_LDU2); // Add the dummy LDU2 data m_rfData.encodeLDU2(data + 2U); // Regenerate the Low Speed Data m_rfLSD.process(data + 2U); // Regenerate Audio unsigned int errors = m_audio.process(data + 2U); LogDebug("P25, LDU2 audio, errs: %u/1233 (%.1f%%)", errors, float(errors) / 12.33F); m_display->writeP25BER(float(errors) / 12.33F); m_rfBits += 1233U; m_rfErrs += errors; m_rfFrames++; m_lastDUID = duid; // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); #if defined(DUMP_P25) writeFile(data + 2U, len - 2U); #endif ::memcpy(m_rfLDU, data + 2U, P25_LDU_FRAME_LENGTH_BYTES); if (m_duplex) { data[0U] = TAG_DATA; data[1U] = 0x00U; writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U); } m_display->writeP25RSSI(m_rssi); return true; } } else if (duid == P25_DUID_TSDU) { if (m_rfState != RS_RF_DATA) { m_rfPDUCount = 0U; m_rfPDUBits = 0U; m_rfState = RS_RF_DATA; m_rfDataFrames = 0U; } bool ret = m_rfData.decodeTSDU(data + 2U); if (!ret) { m_lastDUID = duid; return false; } unsigned int srcId = m_rfData.getSrcId(); unsigned int dstId = m_rfData.getDstId(); unsigned char data[P25_TSDU_FRAME_LENGTH_BYTES + 2U]; switch (m_rfData.getLCF()) { case P25_LCF_TSBK_CALL_ALERT: LogMessage("P25, received RF TSDU transmission, CALL ALERT from %u to %u", srcId, dstId); ::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES); // Regenerate Sync CSync::addP25Sync(data + 2U); // Regenerate NID m_nid.encode(data + 2U, P25_DUID_TSDU); // Regenerate TDULC Data m_rfData.encodeTSDU(data + 2U); // Add busy bits addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false); // Set first busy bits to 1,1 setBusyBits(data + 2U, P25_SS0_START, true, true); if (m_duplex) { data[0U] = TAG_DATA; data[1U] = 0x00U; writeQueueRF(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U); } break; case P25_LCF_TSBK_ACK_RSP_FNE: LogMessage("P25, received RF TSDU transmission, ACK RESPONSE FNE from %u to %u", srcId, dstId); ::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES); // Regenerate Sync CSync::addP25Sync(data + 2U); // Regenerate NID m_nid.encode(data + 2U, P25_DUID_TSDU); // Regenerate TDULC Data m_rfData.encodeTSDU(data + 2U); // Add busy bits addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false); // Set first busy bits to 1,1 setBusyBits(data + 2U, P25_SS0_START, true, true); if (m_duplex) { data[0U] = TAG_DATA; data[1U] = 0x00U; writeQueueRF(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U); } break; default: LogMessage("P25, recieved RF TSDU transmission, unhandled LCF $%02X", m_rfData.getLCF()); break; } m_rfState = RS_RF_LISTENING; return true; } else if (duid == P25_DUID_TERM || duid == P25_DUID_TERM_LC) { if (m_rfState == RS_RF_AUDIO) { writeNetwork(m_rfLDU, m_lastDUID, true); ::memset(data + 2U, 0x00U, P25_TERM_FRAME_LENGTH_BYTES); // Regenerate Sync CSync::addP25Sync(data + 2U); // Regenerate NID m_nid.encode(data + 2U, P25_DUID_TERM); // Add busy bits addBusyBits(data + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true); m_rfState = RS_RF_LISTENING; m_rfTimeout.stop(); m_rfData.reset(); m_lastDUID = duid; if (m_rssi != 0U) LogMessage("P25, received RF end of voice transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); else LogMessage("P25, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); m_display->clearP25(); #if defined(DUMP_P25) closeFile(); #endif writeNetwork(data + 2U, P25_DUID_TERM, true); if (m_duplex) { data[0U] = TAG_EOT; data[1U] = 0x00U; writeQueueRF(data, P25_TERM_FRAME_LENGTH_BYTES + 2U); } } } else if (duid == P25_DUID_PDU) { if (m_rfState != RS_RF_DATA) { m_rfPDUCount = 0U; m_rfPDUBits = 0U; m_rfState = RS_RF_DATA; m_rfDataFrames = 0U; } unsigned int start = m_rfPDUCount * P25_LDU_FRAME_LENGTH_BITS; unsigned char buffer[P25_LDU_FRAME_LENGTH_BYTES]; unsigned int bits = CP25Utils::decode(data + 2U, buffer, start, start + P25_LDU_FRAME_LENGTH_BITS); for (unsigned int i = 0U; i < bits; i++, m_rfPDUBits++) { bool b = READ_BIT(buffer, i); WRITE_BIT(m_rfPDU, m_rfPDUBits, b); } if (m_rfPDUCount == 0U) { CP25Trellis trellis; unsigned char header[P25_PDU_HEADER_LENGTH_BYTES]; bool valid = trellis.decode12(m_rfPDU + P25_SYNC_LENGTH_BYTES + P25_NID_LENGTH_BYTES, header); if (valid) valid = CCRC::checkCCITT162(header, P25_PDU_HEADER_LENGTH_BYTES); if (valid) { unsigned int llId = (header[3U] << 16) + (header[4U] << 8) + header[5U]; unsigned int sap = header[1U] & 0x3FU; m_rfDataFrames = header[6U] & 0x7FU; LogMessage("P25, received RF data transmission for Local Link Id %u, SAP %u, %u blocks", llId, sap, m_rfDataFrames); } else { m_rfPDUCount = 0U; m_rfPDUBits = 0U; m_rfState = RS_RF_LISTENING; m_rfDataFrames = 0U; } } if (m_rfState == RS_RF_DATA) { m_rfPDUCount++; unsigned int bitLength = ((m_rfDataFrames + 1U) * P25_PDU_FEC_LENGTH_BITS) + P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS; if (m_rfPDUBits >= bitLength) { unsigned int offset = P25_SYNC_LENGTH_BYTES + P25_NID_LENGTH_BYTES; // Regenerate the PDU header CP25Trellis trellis; unsigned char header[P25_PDU_HEADER_LENGTH_BYTES]; trellis.decode12(m_rfPDU + offset, header); trellis.encode12(header, m_rfPDU + offset); offset += P25_PDU_FEC_LENGTH_BITS; // Regenerate the PDU data for (unsigned int i = 0U; i < m_rfDataFrames; i++) { unsigned char data[P25_PDU_CONFIRMED_LENGTH_BYTES]; bool valid = trellis.decode34(m_rfPDU + offset, data); if (valid) { trellis.encode34(data, m_rfPDU + offset); } else { valid = trellis.decode12(m_rfPDU + offset, data); if (valid) trellis.encode12(data, m_rfPDU + offset); } offset += P25_PDU_FEC_LENGTH_BITS; } unsigned char pdu[1024U]; // Add the data unsigned int newBitLength = CP25Utils::encode(m_rfPDU, pdu + 2U, bitLength); unsigned int newByteLength = newBitLength / 8U; if ((newBitLength % 8U) > 0U) newByteLength++; // Regenerate Sync CSync::addP25Sync(pdu + 2U); // Regenerate NID m_nid.encode(pdu + 2U, P25_DUID_PDU); // Add busy bits addBusyBits(pdu + 2U, newBitLength, false, true); if (m_duplex) { pdu[0U] = TAG_DATA; pdu[1U] = 0x00U; writeQueueRF(pdu, newByteLength + 2U); } LogMessage("P25, ended RF data transmission"); m_display->clearP25(); m_rfPDUCount = 0U; m_rfPDUBits = 0U; m_rfState = RS_RF_LISTENING; m_rfDataFrames = 0U; } return true; } } return false; }