Пример #1
0
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());
			}
		}
	}
}