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()); } } } }
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()); } } } }