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