Merge remote-tracking branch 'g4klx/master'

This commit is contained in:
Andy CA6JAU
2017-03-20 21:20:06 -03:00
9 changed files with 427 additions and 220 deletions

View File

@@ -85,18 +85,18 @@ bool CDMRControl::processWakeup(const unsigned char* data)
return false;
}
void CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)
bool CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)
{
assert(data != NULL);
m_slot1.writeModem(data, len);
return m_slot1.writeModem(data, len);
}
void CDMRControl::writeModemSlot2(unsigned char *data, unsigned int len)
bool CDMRControl::writeModemSlot2(unsigned char *data, unsigned int len)
{
assert(data != NULL);
m_slot2.writeModem(data, len);
return m_slot2.writeModem(data, len);
}
unsigned int CDMRControl::readModemSlot1(unsigned char *data)

View File

@@ -36,8 +36,8 @@ public:
bool processWakeup(const unsigned char* data);
void writeModemSlot1(unsigned char* data, unsigned int len);
void writeModemSlot2(unsigned char* data, unsigned int len);
bool writeModemSlot1(unsigned char* data, unsigned int len);
bool writeModemSlot2(unsigned char* data, unsigned int len);
unsigned int readModemSlot1(unsigned char* data);
unsigned int readModemSlot2(unsigned char* data);

98
DMRIDUpdateBM.sh Normal file
View File

@@ -0,0 +1,98 @@
#! /bin/bash
###############################################################################
#
# DMRIDUpdate.sh
#
# Copyright (C) 2016 by Tony Corbett G0WFV
# edit by R2AJV
# edit by CT2JAY
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###############################################################################
#
# On a Linux based system, such as a Raspberry Pi, this script will perform all
# the steps required to maintain the DMRIds.dat (or similar) file for you.
#
# It is designed to run from crontab and will download the latest IDs from the
# BM network database and optionally keep a backup of previously
# created files for you.
#
# It will also prune the number of backup files according to a value specified
# by you in the configuration below.
#
# When done, it will restart MMDVMHost to make the ID changes take effect.
#
# To install in root's crontab use the command ...
#
# sudo crontab -e
#
# ... and add the following line to the bottom of the file ...
#
# 0 0 * * * /path/to/script/DMRIDUpdateBM.sh 1>/dev/null 2>&1
#
# ... where /path/to/script/ should be replaced by the path to this script.
#
###############################################################################
#
# CONFIGURATION
#
# Full path to DMR ID file
DMRIDFILE=/path/to/DMR/ID/file/DMRIds.dat
#
# How many DMR ID files do you want backed up (0 = do not keep backups)
DMRFILEBACKUP=1
#
# Command line to restart MMDVMHost
RESTARTCOMMAND="systemctl restart mmdvmhost.service"
# RESTARTCOMMAND="killall MMDVMHost ; /path/to/MMDVMHost/executable/MMDVMHost /path/to/MMDVM/ini/file/MMDVM.ini"
###############################################################################
#
# Do not edit below here
#
###############################################################################
# Check we are root
if [ "$(id -u)" != "0" ]
then
echo "This script must be run as root" 1>&2
exit 1
fi
# Create backup of old file
if [ ${DMRFILEBACKUP} -ne 0 ]
then
cp ${DMRIDFILE} ${DMRIDFILE}.$(date +%d%m%y)
fi
# Prune backups
BACKUPCOUNT=$(ls ${DMRIDFILE}.* | wc -l)
BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${DMRFILEBACKUP})
if [ ${BACKUPCOUNT} -gt ${DMRFILEBACKUP} ]
then
for f in $(ls -tr ${DMRIDFILE}.* | head -${BACKUPSTODELETE})
do
rm $f
done
fi
# Generate new file
curl 'http://registry.dstar.su/dmr/DMRIds.php' 2>/dev/null | sed -e 's/[[:space:]]\+/ /g' > ${DMRIDFILE}
# Restart MMDVMHost
eval ${RESTARTCOMMAND}

View File

@@ -100,6 +100,8 @@ m_rfBits(1U),
m_netBits(1U),
m_rfErrs(0U),
m_netErrs(0U),
m_rfTimeout(false),
m_netTimeout(false),
m_lastFrame(NULL),
m_lastFrameValid(false),
m_rssi(0U),
@@ -124,7 +126,7 @@ CDMRSlot::~CDMRSlot()
delete[] m_lastFrame;
}
void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
{
assert(data != NULL);
@@ -133,19 +135,24 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF(true);
return;
if (m_rfTimeout) {
writeEndRF();
return false;
} else {
writeEndRF(true);
return true;
}
}
if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) {
LogMessage("DMR Slot %u, RF data transmission lost", m_slotNo);
writeEndRF();
return;
return false;
}
if (data[0U] == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
return;
return false;
}
// Have we got RSSI bytes on the end?
@@ -183,12 +190,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (dataType == DT_VOICE_LC_HEADER) {
if (m_rfState == RS_RF_AUDIO)
return;
return true;
CDMRFullLC fullLC;
CDMRLC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
if (lc == NULL)
return;
return false;
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
@@ -197,13 +204,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc;
return;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
delete lc;
return;
return false;
}
m_rfLC = lc;
@@ -226,6 +233,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
data[1U] = 0x00U;
m_rfTimeoutTimer.start();
m_rfTimeout = false;
m_rfFrames = 0U;
m_rfSeqNo = 0U;
@@ -264,9 +272,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
LogMessage("DMR Slot %u, received RF voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
return true;
} else if (dataType == DT_VOICE_PI_HEADER) {
if (m_rfState != RS_RF_AUDIO)
return;
return false;
// Regenerate the Slot Type
slotType.getData(data + 2U);
@@ -287,9 +297,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
writeQueueRF(data);
writeNetworkRF(data, DT_VOICE_PI_HEADER);
return true;
} else if (dataType == DT_TERMINATOR_WITH_LC) {
if (m_rfState != RS_RF_AUDIO)
return;
return false;
// Regenerate the LC data
CDMRFullLC fullLC;
@@ -301,15 +313,17 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
// Convert the Data Sync to be from the BS or MS as needed
CSync::addDMRDataSync(data + 2U, m_duplex);
data[0U] = TAG_EOT;
data[1U] = 0x00U;
if (!m_rfTimeout) {
data[0U] = TAG_EOT;
data[1U] = 0x00U;
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
if (m_duplex) {
for (unsigned int i = 0U; i < m_hangCount; i++)
writeQueueRF(data);
if (m_duplex) {
for (unsigned int i = 0U; i < m_hangCount; i++)
writeQueueRF(data);
}
}
if (m_rssi != 0U)
@@ -317,15 +331,21 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
else
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
if (m_rfTimeout) {
writeEndRF();
return false;
} else {
writeEndRF();
return true;
}
} else if (dataType == DT_DATA_HEADER) {
if (m_rfState == RS_RF_DATA)
return;
return true;
CDMRDataHeader dataHeader;
bool valid = dataHeader.put(data + 2U);
if (!valid)
return;
return false;
bool gi = dataHeader.getGI();
unsigned int srcId = dataHeader.getSrcId();
@@ -333,12 +353,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
return;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
return;
return false;
}
m_rfFrames = dataHeader.getBlocks();
@@ -383,15 +403,17 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo);
writeEndRF();
}
return true;
} else if (dataType == DT_CSBK) {
CDMRCSBK csbk;
bool valid = csbk.put(data + 2U);
if (!valid)
return;
return false;
CSBKO csbko = csbk.getCSBKO();
if (csbko == CSBKO_BSDWNACT)
return;
return false;
bool gi = csbk.getGI();
unsigned int srcId = csbk.getSrcId();
@@ -400,12 +422,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (srcId != 0U || dstId != 0U) {
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
return;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
return;
return false;
}
}
@@ -448,9 +470,11 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
break;
}
return true;
} else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) {
if (m_rfState != RS_RF_DATA || m_rfFrames == 0U)
return;
return false;
// Regenerate the rate 1/2 payload
if (dataType == DT_RATE_12_DATA) {
@@ -490,6 +514,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo);
writeEndRF();
}
return true;
}
} else if (audioSync) {
if (m_rfState == RS_RF_AUDIO) {
@@ -508,23 +534,30 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfBits += 141U;
m_rfFrames++;
data[0U] = TAG_DATA;
data[1U] = 0x00U;
m_rfEmbeddedReadN = (m_rfEmbeddedReadN + 1U) % 2U;
m_rfEmbeddedWriteN = (m_rfEmbeddedWriteN + 1U) % 2U;
m_rfEmbeddedData[m_rfEmbeddedWriteN].reset();
if (m_duplex)
writeQueueRF(data);
writeNetworkRF(data, DT_VOICE_SYNC, errors);
m_display->writeDMRRSSI(m_slotNo, m_rssi);
if (!m_rfTimeout) {
data[0U] = TAG_DATA;
data[1U] = 0x00U;
if (m_duplex)
writeQueueRF(data);
writeNetworkRF(data, DT_VOICE_SYNC, errors);
return true;
}
return false;
} else if (m_rfState == RS_RF_LISTENING) {
m_rfEmbeddedLC.reset();
m_rfState = RS_RF_LATE_ENTRY;
return false;
}
} else {
if (m_rfState == RS_RF_AUDIO) {
@@ -626,23 +659,29 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
emb.setLCSS(lcss);
emb.getData(data + 2U);
data[0U] = TAG_DATA;
data[1U] = 0x00U;
if (!m_rfTimeout) {
data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeNetworkRF(data, DT_VOICE, errors);
writeNetworkRF(data, DT_VOICE, errors);
if (m_embeddedLCOnly) {
// Only send the previously received LC
lcss = m_rfEmbeddedLC.getData(data + 2U, m_rfN);
if (m_embeddedLCOnly) {
// Only send the previously received LC
lcss = m_rfEmbeddedLC.getData(data + 2U, m_rfN);
// Regenerate the EMB
emb.setColorCode(m_colorCode);
emb.setLCSS(lcss);
emb.getData(data + 2U);
// Regenerate the EMB
emb.setColorCode(m_colorCode);
emb.setLCSS(lcss);
emb.getData(data + 2U);
}
if (m_duplex)
writeQueueRF(data);
return true;
}
if (m_duplex)
writeQueueRF(data);
return false;
} else if (m_rfState == RS_RF_LATE_ENTRY) {
CDMREMB emb;
emb.putData(data + 2U);
@@ -650,7 +689,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
// 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;
return false;
m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS());
CDMRLC* lc = m_rfEmbeddedLC.getLC();
@@ -662,13 +701,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
delete lc;
return;
return false;
}
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
delete lc;
return;
return false;
}
m_rfLC = lc;
@@ -695,6 +734,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
start[1U] = 0x00U;
m_rfTimeoutTimer.start();
m_rfTimeout = false;
m_rfFrames = 0U;
m_rfSeqNo = 0U;
@@ -759,9 +799,13 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
LogMessage("DMR Slot %u, received RF late entry from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
return true;
}
}
}
return false;
}
unsigned int CDMRSlot::readModem(unsigned char* data)
@@ -788,14 +832,8 @@ void CDMRSlot::writeEndRF(bool writeEnd)
m_display->clearDMR(m_slotNo);
}
m_rfTimeoutTimer.stop();
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
if (writeEnd) {
if (m_netState == RS_NET_IDLE && m_duplex) {
if (m_netState == RS_NET_IDLE && m_duplex && !m_rfTimeout) {
// Create a dummy start end frame
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
@@ -817,6 +855,13 @@ void CDMRSlot::writeEndRF(bool writeEnd)
}
}
m_rfTimeoutTimer.stop();
m_rfTimeout = false;
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
delete m_rfLC;
m_rfLC = NULL;
}
@@ -831,17 +876,7 @@ void CDMRSlot::writeEndNet(bool writeEnd)
m_lastFrameValid = false;
m_networkWatchdog.stop();
m_netTimeoutTimer.stop();
m_packetTimer.stop();
m_netFrames = 0U;
m_netLost = 0U;
m_netErrs = 0U;
m_netBits = 1U;
if (writeEnd) {
if (writeEnd && !m_netTimeout) {
// Create a dummy start end frame
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
@@ -867,6 +902,17 @@ void CDMRSlot::writeEndNet(bool writeEnd)
}
}
m_networkWatchdog.stop();
m_netTimeoutTimer.stop();
m_packetTimer.stop();
m_netTimeout = false;
m_netFrames = 0U;
m_netLost = 0U;
m_netErrs = 0U;
m_netBits = 1U;
delete m_netLC;
m_netLC = NULL;
@@ -926,6 +972,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastFrameValid = false;
m_netTimeoutTimer.start();
m_netTimeout = false;
m_netFrames = 0U;
m_netLost = 0U;
@@ -974,6 +1021,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastFrameValid = false;
m_netTimeoutTimer.start();
m_netTimeout = false;
if (m_duplex) {
m_queue.clear();
@@ -1063,15 +1111,18 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS or MS as needed
CSync::addDMRDataSync(data + 2U, m_duplex);
data[0U] = TAG_EOT;
data[1U] = 0x00U;
if (!m_netTimeout) {
data[0U] = TAG_EOT;
data[1U] = 0x00U;
if (m_duplex) {
for (unsigned int i = 0U; i < m_hangCount; i++)
writeQueueNet(data);
} else {
for (unsigned int i = 0U; i < 3U; i++)
writeQueueNet(data);
if (m_duplex) {
for (unsigned int i = 0U; i < m_hangCount; i++)
writeQueueNet(data);
}
else {
for (unsigned int i = 0U; i < 3U; i++)
writeQueueNet(data);
}
}
#if defined(DUMP_DMR)
@@ -1155,6 +1206,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastFrameValid = false;
m_netTimeoutTimer.start();
m_netTimeout = false;
if (m_duplex) {
m_queue.clear();
@@ -1231,7 +1283,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
insertSilence(data, dmrData.getSeqNo());
}
writeQueueNet(data);
if (!m_netTimeout)
writeQueueNet(data);
m_netEmbeddedReadN = (m_netEmbeddedReadN + 1U) % 2U;
m_netEmbeddedWriteN = (m_netEmbeddedWriteN + 1U) % 2U;
@@ -1363,7 +1416,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
insertSilence(data, dmrData.getSeqNo());
}
writeQueueNet(data);
if (!m_netTimeout)
writeQueueNet(data);
m_packetTimer.start();
m_elapsed.start();
@@ -1493,7 +1547,20 @@ void CDMRSlot::clock()
m_interval.start();
m_rfTimeoutTimer.clock(ms);
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired()) {
if (!m_rfTimeout) {
LogMessage("DMR Slot %u, RF user has timed out", m_slotNo);
m_rfTimeout = true;
}
}
m_netTimeoutTimer.clock(ms);
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired()) {
if (!m_netTimeout) {
LogMessage("DMR Slot %u, network user has timed out", m_slotNo);
m_netTimeout = true;
}
}
if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA) {
m_networkWatchdog.clock(ms);
@@ -1549,12 +1616,7 @@ void CDMRSlot::writeQueueRF(const unsigned char *data)
}
m_queue.addData(&len, 1U);
// If the timeout has expired, replace the audio with idles to keep the slot busy
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
m_queue.addData(m_idle, len);
else
m_queue.addData(data, len);
m_queue.addData(data, len);
}
void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId, unsigned char errors)
@@ -1567,10 +1629,6 @@ void CDMRSlot::writeNetworkRF(const unsigned char* data, unsigned char dataType,
if (m_network == NULL)
return;
// Don't send to the network if the timeout has expired
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
CDMRData dmrData;
dmrData.setSlotNo(m_slotNo);
dmrData.setDataType(dataType);
@@ -1610,12 +1668,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
}
m_queue.addData(&len, 1U);
// If the timeout has expired, replace the audio with idles to keep the slot busy
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired())
m_queue.addData(m_idle, len);
else
m_queue.addData(data, len);
m_queue.addData(data, len);
}
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter)

View File

@@ -42,7 +42,7 @@ public:
CDMRSlot(unsigned int slotNo, unsigned int timeout);
~CDMRSlot();
void writeModem(unsigned char* data, unsigned int len);
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
@@ -89,6 +89,8 @@ private:
unsigned int m_netBits;
unsigned int m_rfErrs;
unsigned int m_netErrs;
bool m_rfTimeout;
bool m_netTimeout;
unsigned char* m_lastFrame;
bool m_lastFrameValid;
unsigned char m_rssi;

View File

@@ -78,21 +78,21 @@ const char* HEADER4 = "Copyright(C) 2015-2017 by Jonathan Naylor, G4KLX and othe
int main(int argc, char** argv)
{
const char* iniFile = DEFAULT_INI_FILE;
if (argc > 1) {
for (int currentArg = 1; currentArg < argc; ++currentArg) {
std::string arg = argv[currentArg];
if ((arg == "-v") || (arg == "--version")) {
::fprintf(stdout, "MMDVMHost version %s\n", VERSION);
return 0;
} else if (arg.substr(0,1) == "-") {
::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n");
return 1;
} else {
iniFile = argv[currentArg];
}
}
}
const char* iniFile = DEFAULT_INI_FILE;
if (argc > 1) {
for (int currentArg = 1; currentArg < argc; ++currentArg) {
std::string arg = argv[currentArg];
if ((arg == "-v") || (arg == "--version")) {
::fprintf(stdout, "MMDVMHost version %s git #%.7s\n", VERSION, gitversion);
return 0;
} else if (arg.substr(0,1) == "-") {
::fprintf(stderr, "Usage: MMDVMHost [-v|--version] [filename]\n");
return 1;
} else {
iniFile = argv[currentArg];
}
}
}
#if !defined(_WIN32) && !defined(_WIN64)
::signal(SIGTERM, sigHandler);
@@ -484,11 +484,13 @@ int CMMDVMHost::run()
m_dmrTXTimer.start();
}
} else {
dmr->writeModemSlot1(data, len);
dmrBeaconTimer.stop();
m_modeTimer.start();
if (m_duplex)
m_dmrTXTimer.start();
bool ret = dmr->writeModemSlot1(data, len);
if (ret) {
dmrBeaconTimer.stop();
m_modeTimer.start();
if (m_duplex)
m_dmrTXTimer.start();
}
}
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("DMR modem data received when in mode %u", m_mode);
@@ -519,11 +521,13 @@ int CMMDVMHost::run()
m_dmrTXTimer.start();
}
} else {
dmr->writeModemSlot2(data, len);
dmrBeaconTimer.stop();
m_modeTimer.start();
if (m_duplex)
m_dmrTXTimer.start();
bool ret = dmr->writeModemSlot2(data, len);
if (ret) {
dmrBeaconTimer.stop();
m_modeTimer.start();
if (m_duplex)
m_dmrTXTimer.start();
}
}
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("DMR modem data received when in mode %u", m_mode);

View File

@@ -0,0 +1,106 @@
#The data to RSSI.dat by RA4NHY
#Values in the RSSI.dat file are obtained using the MMDVMCal calibration program (S mode), the high-frequency generator and the Motorola GM340UHF radio station.
#For different radio stations, the values are slightly different.
#For example, for those GM340 that I had, the discrepancy is about 10 dB.
#Therefore, it is desirable to carry out calibration for each radio station.
#More about RSSI and a homebrew MMDVM node you can read here https://drive.google.com/file/d/0B_UNZTdPtyZUUjN2d2llV0RtNTQ/view but unfortunately in Russian only
#Anton, RA4NHY
1045 -43
1043 -46
1042 -47
1041 -48
1039 -49
1036 -50
1030 -51
1024 -52
1017 -53
1009 -54
1003 -55
992 -56
980 -57
967 -58
955 -59
941 -60
929 -61
916 -62
905 -63
893 -64
884 -65
874 -66
865 -67
856 -68
848 -69
839 -70
831 -71
823 -72
815 -73
805 -74
799 -75
789 -76
778 -77
767 -78
757 -79
746 -80
737 -81
727 -82
719 -83
711 -84
704 -85
696 -86
689 -87
682 -88
674 -89
667 -90
659 -91
650 -92
641 -93
630 -94
621 -95
610 -96
598 -97
586 -98
575 -99
564 -100
554 -101
544 -102
535 -103
526 -104
521 -105
512 -106
504 -107
495 -108
486 -109
477 -110
468 -111
458 -112
449 -113
439 -114
431 -115
421 -116
412 -117
404 -118
395 -119
387 -120
381 -121
374 -122
368 -123
363 -124
360 -125
355 -126
352 -127
348 -128
345 -129
344 -130
342 -131
340 -132
339 -133
338 -134
337 -135
336 -136
335 -137
334 -138
333 -139
332 -140
331 -141
330 -142

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@@ -40,27 +40,17 @@
#if defined(_WIN32) || defined(_WIN64)
const unsigned int BUFFER_LENGTH = 1000U;
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_assertRTS(assertRTS),
m_handle(INVALID_HANDLE_VALUE),
m_readOverlapped(),
m_writeOverlapped(),
m_readBuffer(NULL),
m_readLength(0U),
m_readPending(false)
m_handle(INVALID_HANDLE_VALUE)
{
assert(!device.empty());
m_readBuffer = new unsigned char[BUFFER_LENGTH];
}
CSerialController::~CSerialController()
{
delete[] m_readBuffer;
}
bool CSerialController::open()
@@ -71,7 +61,7 @@ bool CSerialController::open()
std::string baseName = m_device.substr(4U); // Convert "\\.\COM10" to "COM10"
m_handle = ::CreateFileA(m_device.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
m_handle = ::CreateFileA(m_device.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_handle == INVALID_HANDLE_VALUE) {
LogError("Cannot open device - %s, err=%04lx", m_device.c_str(), ::GetLastError());
return false;
@@ -85,17 +75,18 @@ bool CSerialController::open()
return false;
}
dcb.BaudRate = DWORD(m_speed);
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.fParity = FALSE;
dcb.StopBits = ONESTOPBIT;
dcb.fInX = FALSE;
dcb.fOutX = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.BaudRate = DWORD(m_speed);
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.fParity = FALSE;
dcb.StopBits = ONESTOPBIT;
dcb.fInX = FALSE;
dcb.fOutX = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDsrSensitivity = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
if (::SetCommState(m_handle, &dcb) == 0) {
LogError("Cannot set the attributes for %s, err=%04lx", m_device.c_str(), ::GetLastError());
@@ -139,16 +130,6 @@ bool CSerialController::open()
::ClearCommError(m_handle, &errCode, NULL);
::memset(&m_readOverlapped, 0x00U, sizeof(OVERLAPPED));
::memset(&m_writeOverlapped, 0x00U, sizeof(OVERLAPPED));
m_readOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
m_writeOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
m_readLength = 0U;
m_readPending = false;
::memset(m_readBuffer, 0x00U, BUFFER_LENGTH);
return true;
}
@@ -179,49 +160,29 @@ int CSerialController::readNonblock(unsigned char* buffer, unsigned int length)
assert(m_handle != INVALID_HANDLE_VALUE);
assert(buffer != NULL);
if (length > BUFFER_LENGTH)
length = BUFFER_LENGTH;
if (m_readPending && length != m_readLength) {
::CancelIo(m_handle);
m_readPending = false;
}
m_readLength = length;
if (length == 0U)
return 0;
if (!m_readPending) {
DWORD bytes = 0UL;
BOOL res = ::ReadFile(m_handle, m_readBuffer, m_readLength, &bytes, &m_readOverlapped);
if (res) {
::memcpy(buffer, m_readBuffer, bytes);
return int(bytes);
}
DWORD error = ::GetLastError();
if (error != ERROR_IO_PENDING) {
LogError("Error from ReadFile: %04lx", error);
return -1;
}
m_readPending = true;
}
BOOL res = HasOverlappedIoCompleted(&m_readOverlapped);
if (!res)
return 0;
DWORD bytes = 0UL;
res = ::GetOverlappedResult(m_handle, &m_readOverlapped, &bytes, TRUE);
if (!res) {
LogError("Error from GetOverlappedResult (ReadFile): %04lx", ::GetLastError());
DWORD errors;
COMSTAT status;
if (::ClearCommError(m_handle, &errors, &status) == 0) {
LogError("Error from ClearCommError for %s, err=%04lx", m_device.c_str(), ::GetLastError());
return -1;
}
::memcpy(buffer, m_readBuffer, bytes);
m_readPending = false;
if (status.cbInQue == 0UL)
return 0;
DWORD readLength = status.cbInQue;
if (length < readLength)
readLength = length;
DWORD bytes = 0UL;
BOOL ret = ::ReadFile(m_handle, buffer, readLength, &bytes, NULL);
if (!ret) {
LogError("Error from ReadFile for %s: %04lx", m_device.c_str(), ::GetLastError());
return -1;
}
return int(bytes);
}
@@ -238,19 +199,10 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length)
while (ptr < length) {
DWORD bytes = 0UL;
BOOL res = ::WriteFile(m_handle, buffer + ptr, length - ptr, &bytes, &m_writeOverlapped);
if (!res) {
DWORD error = ::GetLastError();
if (error != ERROR_IO_PENDING) {
LogError("Error from WriteFile: %04lx", error);
return -1;
}
res = ::GetOverlappedResult(m_handle, &m_writeOverlapped, &bytes, TRUE);
if (!res) {
LogError("Error from GetOverlappedResult (WriteFile): %04lx", ::GetLastError());
return -1;
}
BOOL ret = ::WriteFile(m_handle, buffer + ptr, length - ptr, &bytes, NULL);
if (!ret) {
LogError("Error from WriteFile for %s: %04lx", m_device.c_str(), ::GetLastError());
return -1;
}
ptr += bytes;
@@ -265,9 +217,6 @@ void CSerialController::close()
::CloseHandle(m_handle);
m_handle = INVALID_HANDLE_VALUE;
::CloseHandle(m_readOverlapped.hEvent);
::CloseHandle(m_writeOverlapped.hEvent);
}
#else

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@@ -59,11 +59,6 @@ private:
bool m_assertRTS;
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_handle;
OVERLAPPED m_readOverlapped;
OVERLAPPED m_writeOverlapped;
unsigned char* m_readBuffer;
unsigned int m_readLength;
bool m_readPending;
#else
int m_fd;
#endif