Ejemplo n.º 1
0
void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType)
{
	assert(m_lc != NULL);

	if (m_network == NULL)
		return;

	// Don't send to the network if the timeout has expired
	if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired())
		return;

	CDMRData dmrData;
	dmrData.setSlotNo(m_slotNo);
	dmrData.setDataType(dataType);
	dmrData.setSrcId(m_lc->getSrcId());
	dmrData.setDstId(m_lc->getDstId());
	dmrData.setFLCO(m_lc->getFLCO());
	dmrData.setN(m_n);
	dmrData.setSeqNo(m_seqNo);

	m_seqNo++;

	dmrData.setData(data + 2U);

	m_network->write(dmrData);
}
Ejemplo n.º 2
0
void CDMRControl::clock()
{
	if (m_network != NULL) {
		CDMRData data;
		bool ret = m_network->read(data);
		if (ret) {
			unsigned int slotNo = data.getSlotNo();
			switch (slotNo) {
				case 1U: m_slot1.writeNetwork(data); break;
				case 2U: m_slot2.writeNetwork(data); break;
				default: LogError("Invalid slot no %u", slotNo); break;
			}
		}
	}

	m_slot1.clock();
	m_slot2.clock();
}
Ejemplo n.º 3
0
bool CDMRNetwork::write(const CDMRData& data)
{
	if (m_status != RUNNING)
		return false;

	unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
	::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);

	buffer[0U]  = 'D';
	buffer[1U]  = 'M';
	buffer[2U]  = 'R';
	buffer[3U]  = 'D';

	unsigned int srcId = data.getSrcId();
	buffer[5U]  = srcId >> 16;
	buffer[6U]  = srcId >> 8;
	buffer[7U]  = srcId >> 0;

	unsigned int dstId = data.getDstId();
	buffer[8U]  = dstId >> 16;
	buffer[9U]  = dstId >> 8;
	buffer[10U] = dstId >> 0;

	::memcpy(buffer + 11U, m_id, 4U);

	unsigned int slotNo = data.getSlotNo();

	// Individual slot disabling
	if (slotNo == 1U && !m_slot1)
		return false;
	if (slotNo == 2U && !m_slot2)
		return false;

	buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;

	FLCO flco = data.getFLCO();
	buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;

	unsigned int slotIndex = slotNo - 1U;

	unsigned int count = 1U;

	unsigned char dataType = data.getDataType();
	if (dataType == DT_VOICE_SYNC) {
		buffer[15U] |= 0x10U;
	} else if (dataType == DT_VOICE) {
		buffer[15U] |= data.getN();
	} else {
		if (dataType == DT_VOICE_LC_HEADER) {
			m_streamId[slotIndex] = ::rand() + 1U;
			count = 2U;
		}

		if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) {
			m_streamId[slotIndex] = ::rand() + 1U;
			count = 1U;
		}

		buffer[15U] |= (0x20U | dataType);
	}

	buffer[4U] = data.getSeqNo();

	::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);

	data.getData(buffer + 20U);

	buffer[53U] = data.getBER();

	if (m_rssi)
		buffer[54U] = data.getRSSI();
	else
		buffer[54U] = 0x00U;

	if (m_debug)
		CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);

	for (unsigned int i = 0U; i < count; i++)
		write(buffer, HOMEBREW_DATA_PACKET_LENGTH);

	return true;
}
Ejemplo n.º 4
0
bool CDMRNetwork::read(CDMRData& data)
{
	if (m_status != RUNNING)
		return false;

	if (m_rxData.isEmpty())
		return false;

	unsigned char length = 0U;

	m_rxData.getData(&length, 1U);
	m_rxData.getData(m_buffer, length);

	// Is this a data packet?
	if (::memcmp(m_buffer, "DMRD", 4U) != 0)
		return false;

	unsigned char seqNo = m_buffer[4U];

	unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);

	unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);

	unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;

	// DMO mode slot disabling
	if (slotNo == 1U && !m_duplex)
		return false;

	// Individual slot disabling
	if (slotNo == 1U && !m_slot1)
		return false;
	if (slotNo == 2U && !m_slot2)
		return false;

	FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;

	data.setSeqNo(seqNo);
	data.setSlotNo(slotNo);
	data.setSrcId(srcId);
	data.setDstId(dstId);
	data.setFLCO(flco);

	bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
	bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;

	if (dataSync) {
		unsigned char dataType = m_buffer[15U] & 0x0FU;
		data.setData(m_buffer + 20U);
		data.setDataType(dataType);
		data.setN(0U);
	} else if (voiceSync) {
		data.setData(m_buffer + 20U);
		data.setDataType(DT_VOICE_SYNC);
		data.setN(0U);
	} else {
		unsigned char n = m_buffer[15U] & 0x0FU;
		data.setData(m_buffer + 20U);
		data.setDataType(DT_VOICE);
		data.setN(n);
	}

	return true;
}
Ejemplo n.º 5
0
void CDMRSlot::writeNetwork(const CDMRData& dmrData)
{
	if (m_state == SS_RELAYING_RF || m_state == SS_LATE_ENTRY)
		return;

	m_networkWatchdog.start();

	unsigned char dataType = dmrData.getDataType();

	unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
	dmrData.getData(data + 2U);

	if (dataType == DT_VOICE_LC_HEADER) {
		if (m_state != SS_RELAYING_NETWORK) {
			CFullLC fullLC;
			m_lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
			if (m_lc == NULL) {
				LogMessage("DMR Slot %u, bad LC received from the network", m_slotNo);
				return;
			}

			// Regenerate the LC
			fullLC.encode(*m_lc, data + 2U, DT_VOICE_LC_HEADER);

			// Regenerate the Slot Type
			CSlotType slotType;
			slotType.setColorCode(m_colorCode);
			slotType.setDataType(DT_VOICE_LC_HEADER);
			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_playoutTimer.start();
			m_timeoutTimer.start();

			for (unsigned int i = 0U; i < 3U; i++)
				writeNetworkQueue(data);

			m_state = SS_RELAYING_NETWORK;

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

#if defined(DUMP_DMR)
			openFile();
			writeFile(data);
#endif
			LogMessage("DMR Slot %u, received network 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_NETWORK)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_VOICE_PI_HEADER);
		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;

		writeNetworkQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_TERMINATOR_WITH_LC) {
		if (m_state != SS_RELAYING_NETWORK)
			return;

		// Regenerate the LC
		CFullLC fullLC;
		fullLC.encode(*m_lc, data + 2U, DT_TERMINATOR_WITH_LC);

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_TERMINATOR_WITH_LC);
		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_EOT;
		data[1U] = 0x00U;

		writeNetworkQueue(data);
		writeEndOfTransmission();

#if defined(DUMP_DMR)
		writeFile(data);
		closeFile();
#endif
		LogMessage("DMR Slot %u, received network end of transmission", m_slotNo);
	} else if (dataType == DT_VOICE_SYNC) {
		if (m_state != SS_RELAYING_NETWORK)
			return;

		// 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;

		writeNetworkQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_VOICE) {
		if (m_state != SS_RELAYING_NETWORK)
			return;

		unsigned char fid = m_lc->getFID();
		if (fid == FID_ETSI || fid == FID_DMRA)
			; // AMBE FEC

		// Change the color code in the EMB
		CEMB emb;
		emb.putData(data + 2U);
		emb.setColorCode(m_colorCode);
		emb.getData(data + 2U);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeNetworkQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else {
		if (m_state != SS_RELAYING_NETWORK)
			return;

		// Change the Color Code of the Slot Type
		CSlotType slotType;
		slotType.putData(data + 2U);
		slotType.setColorCode(m_colorCode);
		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;

		writeNetworkQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	}
}
Ejemplo n.º 6
0
void CDMRSlot::writeNetwork(const CDMRData& dmrData)
{
	if (m_state == RS_RELAYING_RF_AUDIO || m_state == RS_RELAYING_RF_DATA || m_state == RS_LATE_ENTRY)
		return;

	m_networkWatchdog.start();

	unsigned char dataType = dmrData.getDataType();

	unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
	dmrData.getData(data + 2U);

	if (dataType == DT_VOICE_LC_HEADER) {
		if (m_state == RS_RELAYING_NETWORK_AUDIO)
			return;

		CFullLC fullLC;
		m_lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
		if (m_lc == NULL) {
			LogMessage("DMR Slot %u, bad LC received from the network", m_slotNo);
			return;
		}

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_VOICE_LC_HEADER);
		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_timeoutTimer.start();

		m_frames = 0U;

		m_bits = 1U;
		m_errs = 0U;

		// 540ms of idle to give breathing space for lost frames
		for (unsigned int i = 0U; i < 9U; i++)
			writeQueue(m_idle);

		for (unsigned int i = 0U; i < 3U; i++)
			writeQueue(data);

		m_state = RS_RELAYING_NETWORK_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());

#if defined(DUMP_DMR)
		openFile();
		writeFile(data);
#endif
		LogMessage("DMR Slot %u, received network 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_NETWORK_AUDIO)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_VOICE_PI_HEADER);
		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;

		writeQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_TERMINATOR_WITH_LC) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_TERMINATOR_WITH_LC);
		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_EOT;
		data[1U] = 0x00U;

		writeQueue(data);
		writeEndOfTransmission();

#if defined(DUMP_DMR)
		writeFile(data);
		closeFile();
#endif
		// We've received the voice header and terminator haven't we?
		m_frames += 2U;
		LogMessage("DMR Slot %u, received network end of voice transmission, %u%% packet loss, BER: %u%%", m_slotNo, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
	} else if (dataType == DT_DATA_HEADER) {
		if (m_state == RS_RELAYING_NETWORK_DATA)
			return;

		// Regenerate the Slot Type
		CSlotType slotType;
		slotType.setColorCode(m_colorCode);
		slotType.setDataType(DT_DATA_HEADER);
		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;

		// Put a small delay into starting transmission
		writeQueue(m_idle);
		writeQueue(m_idle);

		for (unsigned i = 0U; i < 3U; i++)
			writeQueue(data);

		m_state = RS_RELAYING_NETWORK_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 network 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 network data header", m_slotNo);
	} else if (dataType == DT_VOICE_SYNC) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Initialise the lost packet data
		if (m_frames == 0U) {
			m_seqNo = dmrData.getSeqNo();
			m_n     = dmrData.getN();
			m_elapsed.start();
			m_lost = 0U;
		} else {
			insertSilence(dmrData.getSeqNo());
		}

		// 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;

		writeQueue(data);

		m_packetTimer.start();
		m_frames++;

		// Save details in case we need to infill data
		m_seqNo = dmrData.getSeqNo();
		m_n     = dmrData.getN();
		::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else if (dataType == DT_VOICE) {
		if (m_state != RS_RELAYING_NETWORK_AUDIO)
			return;

		// Initialise the lost packet data
		if (m_frames == 0U) {
			m_seqNo = dmrData.getSeqNo();
			m_n     = dmrData.getN();
			m_elapsed.start();
			m_lost = 0U;
		} else {
			insertSilence(dmrData.getSeqNo());
		}

		unsigned char fid = m_lc->getFID();
		if (fid == FID_ETSI || fid == FID_DMRA)
			m_errs += m_fec.regenerateDMR(data + 2U);
		m_bits += 216U;

		// Change the color code in the EMB
		CEMB emb;
		emb.putData(data + 2U);
		emb.setColorCode(m_colorCode);
		emb.getData(data + 2U);

		data[0U] = TAG_DATA;
		data[1U] = 0x00U;

		writeQueue(data);

		m_packetTimer.start();
		m_frames++;

		// Save details in case we need to infill data
		m_seqNo = dmrData.getSeqNo();
		m_n     = dmrData.getN();
		::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	} else {
		// Change the Color Code of the Slot Type
		CSlotType slotType;
		slotType.putData(data + 2U);
		slotType.setColorCode(m_colorCode);
		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;

		writeQueue(data);

#if defined(DUMP_DMR)
		writeFile(data);
#endif
	}
}