Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Simon 2016-11-18 13:46:42 +00:00
commit 97cdfb97e8
41 changed files with 1522 additions and 235 deletions

View file

@ -21,39 +21,39 @@
#include <cstring>
std::vector<unsigned int> DMRAccessControl::m_dstBlackListSlot1RF;
std::vector<unsigned int> DMRAccessControl::m_dstBlackListSlot2RF;
std::vector<unsigned int> DMRAccessControl::m_dstWhiteListSlot1RF;
std::vector<unsigned int> DMRAccessControl::m_dstWhiteListSlot2RF;
std::vector<unsigned int> CDMRAccessControl::m_dstBlackListSlot1RF;
std::vector<unsigned int> CDMRAccessControl::m_dstBlackListSlot2RF;
std::vector<unsigned int> CDMRAccessControl::m_dstWhiteListSlot1RF;
std::vector<unsigned int> CDMRAccessControl::m_dstWhiteListSlot2RF;
std::vector<unsigned int> DMRAccessControl::m_dstBlackListSlot1NET;
std::vector<unsigned int> DMRAccessControl::m_dstBlackListSlot2NET;
std::vector<unsigned int> DMRAccessControl::m_dstWhiteListSlot1NET;
std::vector<unsigned int> DMRAccessControl::m_dstWhiteListSlot2NET;
std::vector<unsigned int> CDMRAccessControl::m_dstBlackListSlot1NET;
std::vector<unsigned int> CDMRAccessControl::m_dstBlackListSlot2NET;
std::vector<unsigned int> CDMRAccessControl::m_dstWhiteListSlot1NET;
std::vector<unsigned int> CDMRAccessControl::m_dstWhiteListSlot2NET;
std::vector<unsigned int> DMRAccessControl::m_srcIdBlacklist;
std::vector<unsigned int> CDMRAccessControl::m_srcIdBlacklist;
std::vector<unsigned int> DMRAccessControl::m_prefixes;
std::vector<unsigned int> CDMRAccessControl::m_prefixes;
bool DMRAccessControl::m_selfOnly = false;
bool CDMRAccessControl::m_selfOnly = false;
unsigned int DMRAccessControl::m_id = 0U;
unsigned int CDMRAccessControl::m_id = 0U;
unsigned int DMRAccessControl::m_dstRewriteID[2];
unsigned int DMRAccessControl::m_srcID[2];
unsigned int CDMRAccessControl::m_dstRewriteID[2];
unsigned int CDMRAccessControl::m_srcID[2];
CDMRLC* DMRAccessControl::m_lastdmrLC;
CDMRLC* CDMRAccessControl::m_lastdmrLC;
time_t DMRAccessControl::m_time[2];
time_t CDMRAccessControl::m_time[2];
int DMRAccessControl::m_callHang;
int CDMRAccessControl::m_callHang;
bool DMRAccessControl::m_tgRewriteSlot1;
bool DMRAccessControl::m_tgRewriteSlot2;
bool DMRAccessControl::m_bmAutoRewrite;
bool DMRAccessControl::m_bmRewriteReflectorVoicePrompts;
bool CDMRAccessControl::m_tgRewriteSlot1;
bool CDMRAccessControl::m_tgRewriteSlot2;
bool CDMRAccessControl::m_bmAutoRewrite;
bool CDMRAccessControl::m_bmRewriteReflectorVoicePrompts;
void DMRAccessControl::init(const std::vector<unsigned int>& dstIdBlacklistSlot1RF, const std::vector<unsigned int>& dstIdWhitelistSlot1RF, const std::vector<unsigned int>& dstIdBlacklistSlot2RF, const std::vector<unsigned int>& dstIdWhitelistSlot2RF, const std::vector<unsigned int>& dstIdBlacklistSlot1NET, const std::vector<unsigned int>& dstIdWhitelistSlot1NET, const std::vector<unsigned int>& dstIdBlacklistSlot2NET, const std::vector<unsigned int>& dstIdWhitelistSlot2NET, const std::vector<unsigned int>& srcIdBlacklist, bool selfOnly, const std::vector<unsigned int>& prefixes, unsigned int id, unsigned int callHang, bool tgRewriteSlot1, bool tgRewriteSlot2, bool bmAutoRewrite, bool bmRewriteReflectorVoicePrompts)
void CDMRAccessControl::init(const std::vector<unsigned int>& dstIdBlacklistSlot1RF, const std::vector<unsigned int>& dstIdWhitelistSlot1RF, const std::vector<unsigned int>& dstIdBlacklistSlot2RF, const std::vector<unsigned int>& dstIdWhitelistSlot2RF, const std::vector<unsigned int>& dstIdBlacklistSlot1NET, const std::vector<unsigned int>& dstIdWhitelistSlot1NET, const std::vector<unsigned int>& dstIdBlacklistSlot2NET, const std::vector<unsigned int>& dstIdWhitelistSlot2NET, const std::vector<unsigned int>& srcIdBlacklist, bool selfOnly, const std::vector<unsigned int>& prefixes, unsigned int id, unsigned int callHang, bool tgRewriteSlot1, bool tgRewriteSlot2, bool bmAutoRewrite, bool bmRewriteReflectorVoicePrompts)
{
m_dstBlackListSlot1RF = dstIdBlacklistSlot1RF;
m_dstWhiteListSlot1RF = dstIdWhitelistSlot1RF;
@ -70,7 +70,7 @@ void DMRAccessControl::init(const std::vector<unsigned int>& dstIdBlacklistSlot1
m_bmRewriteReflectorVoicePrompts = bmRewriteReflectorVoicePrompts;
}
bool DMRAccessControl::dstIdBlacklist(unsigned int did, unsigned int slot, bool network)
bool CDMRAccessControl::dstIdBlacklist(unsigned int did, unsigned int slot, bool network)
{
static std::vector<unsigned int> blacklist;
@ -89,7 +89,7 @@ bool DMRAccessControl::dstIdBlacklist(unsigned int did, unsigned int slot, bool
return std::find(blacklist.begin(), blacklist.end(), did) != blacklist.end();
}
bool DMRAccessControl::dstIdWhitelist(unsigned int did, unsigned int slot, bool gt4k, bool network)
bool CDMRAccessControl::dstIdWhitelist(unsigned int did, unsigned int slot, bool gt4k, bool network)
{
if (network) {
if (slot == 1U) {
@ -166,7 +166,7 @@ bool DMRAccessControl::dstIdWhitelist(unsigned int did, unsigned int slot, bool
}
}
bool DMRAccessControl::validateSrcId(unsigned int id)
bool CDMRAccessControl::validateSrcId(unsigned int id)
{
if (m_selfOnly) {
return id == m_id;
@ -185,16 +185,16 @@ bool DMRAccessControl::validateSrcId(unsigned int id)
}
}
bool DMRAccessControl::validateAccess(unsigned int src_id, unsigned int dst_id, unsigned int slot, bool network)
bool CDMRAccessControl::validateAccess(unsigned int src_id, unsigned int dst_id, unsigned int slot, bool network)
{
// source ID validation is only applied to RF traffic
if (!network && !DMRAccessControl::validateSrcId(src_id)) {
if (!network && !CDMRAccessControl::validateSrcId(src_id)) {
LogMessage("DMR Slot %u, invalid access attempt from %u (blacklisted)", slot, src_id);
return false;
} else if (DMRAccessControl::dstIdBlacklist(dst_id, slot, network)) {
} else if (CDMRAccessControl::dstIdBlacklist(dst_id, slot, network)) {
LogMessage("DMR Slot %u, invalid access attempt to TG%u (TG blacklisted)", slot, dst_id);
return false;
} else if (!DMRAccessControl::dstIdWhitelist(dst_id, slot, true, network)) {
} else if (!CDMRAccessControl::dstIdWhitelist(dst_id, slot, true, network)) {
LogMessage("DMR Slot %u, invalid access attempt to TG%u (TG not in whitelist)", slot, dst_id);
return false;
} else {
@ -202,7 +202,7 @@ bool DMRAccessControl::validateAccess(unsigned int src_id, unsigned int dst_id,
}
}
unsigned int DMRAccessControl::dstIdRewrite(unsigned int did, unsigned int sid, unsigned int slot, bool network, CDMRLC* dmrLC)
unsigned int CDMRAccessControl::dstIdRewrite(unsigned int did, unsigned int sid, unsigned int slot, bool network, CDMRLC* dmrLC)
{
if (slot == 1U && !m_tgRewriteSlot1)
return 0U;
@ -213,39 +213,38 @@ unsigned int DMRAccessControl::dstIdRewrite(unsigned int did, unsigned int sid,
time_t currenttime = ::time(NULL);
if (network) {
m_dstRewriteID[slot - 1U] = did;
m_srcID[slot - 1U] = sid;
//not needed at present - for direct dial, which requires change at master end.
// Not needed at present - for direct dial, which requires change at master end.
//memcpy(&m_lastdmrLC, &dmrLC, sizeof(dmrLC));
if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && dmrLC->getFLCO() == FLCO_GROUP ) {
LogMessage("DMR Slot %u, Rewrite DST ID (TG) of of inbound network traffic from %u to 9",slot,did);
if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && dmrLC->getFLCO() == FLCO_GROUP) {
LogMessage("DMR Slot %u, Rewrite DST ID (TG) of of inbound network traffic from %u to 9", slot, did);
return 9U;
// rewrite incoming BM voice prompts to TG 9
// Rewrite incoming BM voice prompts to TG 9
} else if (m_bmRewriteReflectorVoicePrompts && (sid >= 4000U && sid <= 5000U) && dmrLC->getFLCO() == FLCO_USER_USER) {
dmrLC->setFLCO(FLCO_GROUP);
LogMessage("DMR Slot %u, Rewrite inbound private call to %u to Group Call on TG 9 (BM reflector voice prompt)",slot,did);
LogMessage("DMR Slot %u, Rewrite inbound private call to %u to Group Call on TG 9 (BM reflector voice prompt)", slot, did);
return 9U;
} else {
return 0U;
}
} else if (m_bmAutoRewrite && did == 9U && m_dstRewriteID[slot - 1U] != 9U && m_dstRewriteID[slot - 1U] != 0U && (m_time[slot - 1U] + m_callHang) > currenttime && dmrLC->getFLCO() == FLCO_GROUP ) {
LogMessage("DMR Slot %u, Rewrite DST ID (TG) of outbound network traffic from %u to %u (return traffic during CallHang)",slot,did,m_dstRewriteID[slot - 1]);
} else if (m_bmAutoRewrite && did == 9U && m_dstRewriteID[slot - 1U] != 9U && m_dstRewriteID[slot - 1U] != 0U && (m_time[slot - 1U] + m_callHang) > currenttime && dmrLC->getFLCO() == FLCO_GROUP) {
LogMessage("DMR Slot %u, Rewrite DST ID (TG) of outbound network traffic from %u to %u (return traffic during CallHang)", slot, did, m_dstRewriteID[slot - 1U]);
return m_dstRewriteID[slot - 1U];
} else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did !=9U && did < 99999U && dmrLC->getFLCO() == FLCO_USER_USER) {
} else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did < 99999U && dmrLC->getFLCO() == FLCO_USER_USER) {
m_dstRewriteID[slot - 1U] = did;
dmrLC->setFLCO(FLCO_GROUP);
LogMessage("DMR Slot %u, Rewrite outbound private call to %u Group Call (Connect talkgroup by private call)",slot,did);
LogMessage("DMR Slot %u, Rewrite outbound private call to %u Group Call (Connect talkgroup by private call)", slot, did);
return did;
} else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did !=9U && did > 99999U) {
} else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did > 99999U) {
m_dstRewriteID[slot - 1U] = did;
}
return 0U;
}
void DMRAccessControl::setOverEndTime(unsigned int slot)
void CDMRAccessControl::setOverEndTime(unsigned int slot)
{
m_time[slot - 1U] = ::time(NULL);
}

View file

@ -20,10 +20,12 @@
#include "DMRLC.h"
class DMRAccessControl {
class CDMRAccessControl {
public:
static bool validateAccess(unsigned int srcId, unsigned int dstId, unsigned int slot, bool network);
static bool validateSrcId(unsigned int id);
static void init(const std::vector<unsigned int>& dstIdBlacklistSlot1RF, const std::vector<unsigned int>& dstIdWhitelistSlot1RF, const std::vector<unsigned int>& dstIdBlacklistSlot2RF, const std::vector<unsigned int>& dstIdWhitelistSlot2RF, const std::vector<unsigned int>& dstIdBlacklistSlot1NET, const std::vector<unsigned int>& dstIdWhitelistSlot1NET, const std::vector<unsigned int>& dstIdBlacklistSlot2NET, const std::vector<unsigned int>& dstIdWhitelistSlot2NET, const std::vector<unsigned int>& srcIdBlacklist, bool selfOnly, const std::vector<unsigned int>& prefixes,unsigned int id,unsigned int callHang, bool tgRewrteSlot1, bool tgRewrteSlot2, bool m_bmAutoRewrite, bool m_bmRewriteReflectorVoicePrompts);
static unsigned int dstIdRewrite(unsigned int id, unsigned int sid, unsigned int slot, bool network, CDMRLC* dmrLC);
@ -53,15 +55,11 @@ private:
static bool dstIdBlacklist(unsigned int did, unsigned int slot, bool network);
static bool dstIdWhitelist(unsigned int did, unsigned int slot, bool gt4k, bool network);
static bool validateSrcId(unsigned int id);
static time_t m_time[2];
static unsigned int m_dstRewriteID[2];
static unsigned int m_srcID[2];
static bool m_tgRewriteSlot1;
static bool m_tgRewriteSlot2;
static bool m_bmAutoRewrite;

View file

@ -12,6 +12,7 @@
*/
#include "DMRControl.h"
#include "DMRAccessControl.h"
#include "Defines.h"
#include "DMRCSBK.h"
#include "Log.h"
@ -20,23 +21,24 @@
#include <cassert>
#include <algorithm>
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF, const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool TGRewriteSlot1, bool TGRewriteSlot2, bool BMAutoRewrite, bool BMRewriteReflectorVoicePrompts) :
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& dstIdBlacklistSlot1RF, const std::vector<unsigned int>& dstIdWhitelistSlot1RF, const std::vector<unsigned int>& dstIdBlacklistSlot2RF, const std::vector<unsigned int>& dstIdWhitelistSlot2RF, const std::vector<unsigned int>& dstIdBlacklistSlot1NET, const std::vector<unsigned int>& dstIdWhitelistSlot1NET, const std::vector<unsigned int>& dstIdBlacklistSlot2NET, const std::vector<unsigned int>& dstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool tgRewriteSlot1, bool tgRewriteSlot2, bool bmAutoRewrite, bool bmRewriteReflectorVoicePrompts) :
m_id(id),
m_colorCode(colorCode),
m_selfOnly(selfOnly),
m_prefixes(prefixes),
m_blackList(blackList),
m_modem(modem),
m_network(network),
m_slot1(1U, timeout),
m_slot2(2U, timeout),
m_lookup(lookup)
{
assert(id != 0U);
assert(modem != NULL);
assert(display != NULL);
assert(lookup != NULL);
CDMRSlot::init(id, colorCode, callHang, selfOnly, prefixes, blackList, DstIdBlacklistSlot1RF, DstIdWhitelistSlot1RF, DstIdBlacklistSlot2RF, DstIdWhitelistSlot2RF, DstIdBlacklistSlot1NET, DstIdWhitelistSlot1NET, DstIdBlacklistSlot2NET, DstIdWhitelistSlot2NET, modem, network, display, duplex, m_lookup, rssiMultiplier, rssiOffset, jitter, TGRewriteSlot1, TGRewriteSlot2, BMAutoRewrite, BMRewriteReflectorVoicePrompts);
// Load black and white lists to DMRAccessControl
CDMRAccessControl::init(dstIdBlacklistSlot1RF, dstIdWhitelistSlot1RF, dstIdBlacklistSlot2RF, dstIdWhitelistSlot2RF, dstIdBlacklistSlot1NET, dstIdWhitelistSlot1NET, dstIdBlacklistSlot2NET, dstIdWhitelistSlot2NET, blacklist, selfOnly, prefixes, id, callHang, tgRewriteSlot1, tgRewriteSlot2, bmAutoRewrite, bmRewriteReflectorVoicePrompts);
CDMRSlot::init(colorCode, callHang, modem, network, display, duplex, m_lookup, rssiMultiplier, rssiOffset, jitter);
}
CDMRControl::~CDMRControl()
@ -65,29 +67,10 @@ bool CDMRControl::processWakeup(const unsigned char* data)
std::string src = m_lookup->find(srcId);
if (m_selfOnly) {
if (srcId != m_id) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str());
return false;
}
} else {
if (std::find(m_blackList.begin(), m_blackList.end(), srcId) != m_blackList.end()) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str());
return false;
}
unsigned int prefix = srcId / 10000U;
if (prefix == 0U || prefix > 999U) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str());
return false;
}
if (m_prefixes.size() > 0U) {
if (std::find(m_prefixes.begin(), m_prefixes.end(), prefix) == m_prefixes.end()) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str());
return false;
}
}
bool ret = CDMRAccessControl::validateSrcId(srcId);
if (!ret) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str());
return false;
}
if (bsId == 0xFFFFFFU) {

View file

@ -30,7 +30,7 @@
class CDMRControl {
public:
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF,const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool TGRewriteSlot1, bool TGRewriteSlot2, bool BMAutoRewrite, bool BMRewriteReflectorVoicePrompts);
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& dstIdBlacklistSlot1RF, const std::vector<unsigned int>& dstIdWhitelistSlot1RF, const std::vector<unsigned int>& dstIdBlacklistSlot2RF, const std::vector<unsigned int>& dstIdWhitelistSlot2RF,const std::vector<unsigned int>& dstIdBlacklistSlot1NET, const std::vector<unsigned int>& dstIdWhitelistSlot1NET, const std::vector<unsigned int>& dstIdBlacklistSlot2NET, const std::vector<unsigned int>& dstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool tgRewriteSlot1, bool tgRewriteSlot2, bool bmAutoRewrite, bool bmRewriteReflectorVoicePrompts);
~CDMRControl();
bool processWakeup(const unsigned char* data);
@ -44,16 +44,13 @@ public:
void clock();
private:
unsigned int m_id;
unsigned int m_colorCode;
bool m_selfOnly;
std::vector<unsigned int> m_prefixes;
std::vector<unsigned int> m_blackList;
CModem* m_modem;
CDMRNetwork* m_network;
CDMRSlot m_slot1;
CDMRSlot m_slot2;
CDMRLookup* m_lookup;
unsigned int m_id;
unsigned int m_colorCode;
CModem* m_modem;
CDMRNetwork* m_network;
CDMRSlot m_slot1;
CDMRSlot m_slot2;
CDMRLookup* m_lookup;
};
#endif

1145
DMRIds.dat

File diff suppressed because it is too large Load diff

View file

@ -361,17 +361,26 @@ void CDMRNetwork::clock(unsigned int ms)
} else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) {
switch (m_status) {
case WAITING_LOGIN:
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
LogDebug("DMR, Sending authorisation");
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
writeAuthorisation();
m_status = WAITING_AUTHORISATION;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_AUTHORISATION:
LogDebug("DMR, Sending configuration");
writeConfig();
m_status = WAITING_CONFIG;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_CONFIG:
if (m_options.empty()) {
writeConfig();
m_status = WAITING_CONFIG;
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
} else {
LogDebug("DMR, Sending options");
writeOptions();
m_status = WAITING_OPTIONS;
}
@ -379,12 +388,6 @@ void CDMRNetwork::clock(unsigned int ms)
m_retryTimer.start();
break;
case WAITING_OPTIONS:
writeConfig();
m_status = WAITING_CONFIG;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case WAITING_CONFIG:
LogMessage("DMR, Logged into the master successfully");
m_status = RUNNING;
m_timeoutTimer.start();
@ -473,9 +476,12 @@ bool CDMRNetwork::writeAuthorisation()
bool CDMRNetwork::writeOptions()
{
char buffer[300U];
::sprintf(buffer, "RPTO%s", m_options.c_str());
return write((unsigned char*)buffer, (unsigned int)::strlen(buffer));
::memcpy(buffer + 0U, "RPTO", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::strcpy(buffer + 8U, m_options.c_str());
return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U);
}
bool CDMRNetwork::writeConfig()
@ -516,7 +522,7 @@ bool CDMRNetwork::writeConfig()
char longitude[20U];
::sprintf(longitude, "%09f", m_longitude);
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%.8s%.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
m_rxFrequency, m_txFrequency, m_power, m_colorCode, latitude, longitude, m_height, m_location.c_str(),
m_description.c_str(), slots, m_url.c_str(), m_version, software);
@ -553,7 +559,7 @@ bool CDMRNetwork::write(const unsigned char* data, unsigned int length)
bool ret = m_socket.write(data, length, m_address, m_port);
if (!ret) {
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
close();
m_socket.close();
open();
return false;
}

View file

@ -71,8 +71,8 @@ private:
WAITING_CONNECT,
WAITING_LOGIN,
WAITING_AUTHORISATION,
WAITING_OPTIONS,
WAITING_CONFIG,
WAITING_OPTIONS,
RUNNING
};

View file

@ -28,11 +28,7 @@
#include <ctime>
#include <algorithm>
unsigned int CDMRSlot::m_id = 0U;
unsigned int CDMRSlot::m_colorCode = 0U;
bool CDMRSlot::m_selfOnly = false;
std::vector<unsigned int> CDMRSlot::m_prefixes;
std::vector<unsigned int> CDMRSlot::m_blackList;
CModem* CDMRSlot::m_modem = NULL;
CDMRNetwork* CDMRSlot::m_network = NULL;
@ -155,12 +151,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false)) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false)) {
delete lc;
return;
}
unsigned int rewriteId = DMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, false, lc);
unsigned int rewriteId = CDMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, false, lc);
if (rewriteId != 0U) {
lc->setDstId(rewriteId);
dstId = rewriteId;
@ -263,7 +259,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
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();
DMRAccessControl::setOverEndTime(m_slotNo);
CDMRAccessControl::setOverEndTime(m_slotNo);
} else if (dataType == DT_DATA_HEADER) {
if (m_rfState == RS_RF_DATA)
return;
@ -277,7 +273,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int srcId = dataHeader.getSrcId();
unsigned int dstId = dataHeader.getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false))
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false))
return;
m_rfFrames = dataHeader.getBlocks();
@ -333,8 +329,10 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int srcId = csbk.getSrcId();
unsigned int dstId = csbk.getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false))
return;
if (srcId != 0U || dstId != 0U) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false))
return;
}
// Regenerate the CSBK data
csbk.get(data + 2U);
@ -491,12 +489,12 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false)) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, false)) {
delete lc;
return;
}
unsigned int rewriteId = DMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, false, lc);
unsigned int rewriteId = CDMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, false, lc);
if (rewriteId != 0U) {
lc->setDstId(rewriteId);
dstId = rewriteId;
@ -778,7 +776,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
delete lc;
return;
}
@ -786,7 +784,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netLC = lc;
// Test dst rewrite
unsigned int rewriteId = DMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
unsigned int rewriteId = CDMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
if (rewriteId != 0U) {
m_netLC->setDstId(rewriteId);
dstId = rewriteId;
@ -853,7 +851,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
delete lc;
return;
}
@ -861,7 +859,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netLC = lc;
// Test dst rewrite
unsigned int rewriteId = DMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
unsigned int rewriteId = CDMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
if (rewriteId != 0U) {
m_netLC->setDstId(rewriteId);
dstId = rewriteId;
@ -979,7 +977,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
LogMessage("DMR Slot %u, received network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
writeEndNet();
DMRAccessControl::setOverEndTime(m_slotNo);
CDMRAccessControl::setOverEndTime(m_slotNo);
} else if (dataType == DT_DATA_HEADER) {
if (m_netState == RS_NET_DATA)
return;
@ -997,7 +995,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int srcId = dataHeader.getSrcId();
unsigned int dstId = dataHeader.getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true))
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true))
return;
m_netFrames = dataHeader.getBlocks();
@ -1043,7 +1041,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int dstId = lc->getDstId();
unsigned int srcId = lc->getSrcId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true)) {
delete lc;
return;
}
@ -1051,7 +1049,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netLC = lc;
// Test dst rewrite
unsigned int rewriteId = DMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
unsigned int rewriteId = CDMRAccessControl::dstIdRewrite(dstId, srcId, m_slotNo, true, m_netLC);
if (rewriteId != 0U) {
m_netLC->setDstId(rewriteId);
dstId = rewriteId;
@ -1209,9 +1207,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
unsigned int srcId = csbk.getSrcId();
unsigned int dstId = csbk.getDstId();
if (!DMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true))
return;
if (srcId != 0U || dstId != 0U) {
if (!CDMRAccessControl::validateAccess(srcId, dstId, m_slotNo, true))
return;
}
// Regenerate the CSBK data
csbk.get(data + 2U);
@ -1431,18 +1431,13 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
m_queue.addData(data, len);
}
void CDMRSlot::init(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& SrcIdBlacklist, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF, const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool TGRewriteSlot1, bool TGRewriteSlot2, bool BMAutoRewrite, bool BMRewriteReflectorVoicePrompts)
void CDMRSlot::init(unsigned int colorCode, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter)
{
assert(id != 0U);
assert(modem != NULL);
assert(display != NULL);
assert(lookup != NULL);
m_id = id;
m_colorCode = colorCode;
m_selfOnly = selfOnly;
m_prefixes = prefixes;
// m_blackList = blackList;
m_modem = modem;
m_network = network;
m_display = display;
@ -1464,9 +1459,6 @@ void CDMRSlot::init(unsigned int id, unsigned int colorCode, unsigned int callHa
slotType.setColorCode(colorCode);
slotType.setDataType(DT_IDLE);
slotType.getData(m_idle + 2U);
//Load black and white lists to DMRAccessControl
DMRAccessControl::init(DstIdBlacklistSlot1RF, DstIdWhitelistSlot1RF, DstIdBlacklistSlot2RF, DstIdWhitelistSlot2RF, DstIdBlacklistSlot1NET, DstIdWhitelistSlot1NET, DstIdBlacklistSlot2NET, DstIdWhitelistSlot2NET, SrcIdBlacklist, m_selfOnly, m_prefixes, m_id,callHang, TGRewriteSlot1, TGRewriteSlot2, BMAutoRewrite, BMRewriteReflectorVoicePrompts);
}

View file

@ -50,7 +50,7 @@ public:
void clock();
static void init(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& SrcIdBlackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF, const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter, bool TGRewriteSlot1, bool TGRewriteSlot2, bool BMAutoRewrite, bool BMRewriteReflectorVoicePrompts);
static void init(unsigned int colorCode, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter);
private:
unsigned int m_slotNo;
@ -87,11 +87,7 @@ private:
unsigned char m_rssi;
FILE* m_fp;
static unsigned int m_id;
static unsigned int m_colorCode;
static bool m_selfOnly;
static std::vector<unsigned int> m_prefixes;
static std::vector<unsigned int> m_blackList;
static CModem* m_modem;
static CDMRNetwork* m_network;

View file

@ -0,0 +1,32 @@
# DMRplus - Startup Options
## Introduction
This file is to give an overview over the Options-parameter in MMDVM.ini [DMR Network]-section.
## Example
You can pull some conection-info at startup to the DMRplus-Network to define the behavior of TS1 and TS2 in DMR-mode.
An example of such a line would be following:
Options=StartRef=4013;RelinkTime=15;UserLink=1;TS1_1=262;TS1_2=1;TS1_3=20;TS1_4=110;TS1_5=270;
If an option is set, it overwrites the setting preset at the master, if an option is empty, it unsets a predefined setting from
the master. If an option is not set, the default from the master would be taken over.
## What the parameters are about?
Here is a quick explaination about the options to be set:
* StartRef: This is the default reflector in TS2, in example: Refl. 4013
* RelinkTime: This is the time to fall back to the default-reflector if linked to another one and no local traffic is done,
not yet implemented, would come next
* UserLink: This defines, if users are allowed to link to another reflector (other than defined as startreflector)
* 1 = allow
* 0 = disallow
* TS1_1: This is the first of 5 talkgroups that could be set static, in example: TG262
* TS1_2: This is the second of 5 talkgroups that could be set static, in example: TG1
* TS1_3: This is the third of 5 talkgroups that could be set static, in example: TG20
* TS1_4: This is the fourth of 5 talkgroups that could be set static, in example: TG110
* TS1_5: This is the fifth of 5 talkgroups that could be set static, in example: TG270
---
Info created by DG9VH 2016-11-11

View file

@ -1,9 +0,0 @@
G0WFV's HD44780 todo list ...
As I only have a 2x16 screen at the moment, development has been done based
on this size screen. Where it is simple, I have attempted ***but not tested***
to implement functions for larger screens.
Here's a list of things I would like to accomplish in the near future ...
- Nothing planned at this time! Any suggestions?

View file

@ -16,6 +16,35 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Some LCD displays include additional LEDs for status.
* If they exist, the LDCproc server will use the output command.
* If the LEDs do not exist, the command is ignored.
* to control these LEDs Below are the values for the Crystalfontz CFA-635.
* N4IRS
* LED 1 (DMR)
* Green 1 0000 0001
* Red 16 0001 0000
* Yellow 17 0001 0001
* LED 2 (P25)
* Green 2 0000 0010
* Red 32 0010 0000
* Yellow 34 0010 0010
* LED 3 (Fusion)
* Green 4 0000 0100
* Red 64 0100 0000
* Yellow 68 1000 0100
* LED 4 (D-Star)
* Green 8 0000 1000
* Red 128 1000 0000
* Yellow 136 1000 1000
*/
#include "LCDproc.h"
#include "Log.h"
@ -23,6 +52,7 @@
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <clocale>
#include <ctime>
#if !defined(_WIN32) && !defined(_WIN64)
@ -85,7 +115,7 @@ bool CLCDproc::open()
server = m_address.c_str();
port = m_port;
localPort = m_localPort;
/* Create TCP socket */
m_socketfd = socket(AF_INET, SOCK_STREAM, 0);
@ -120,6 +150,7 @@ bool CLCDproc::open()
}
socketPrintf(m_socketfd, "hello"); // Login to the LCD server
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
return true;
}
@ -134,6 +165,7 @@ void CLCDproc::setIdleInt()
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Idle", m_cols - 3, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
m_dmr = false;
@ -151,6 +183,7 @@ void CLCDproc::setErrorInt(const char* text)
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Error", m_cols - 4, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
m_dmr = false;
@ -166,11 +199,14 @@ void CLCDproc::setLockoutInt()
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Lockout", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
m_dmr = false;
}
// LED 4 Green 8 Red 128 Yellow 136
void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{
assert(my1 != NULL);
@ -185,7 +221,7 @@ void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your,
socketPrintf(m_socketfd, "widget_set DStar Mode 1 1 \"D-Star\"");
::sprintf(m_displayBuffer1, "%.8s", your);
char *p = m_displayBuffer1;
for (; *p; ++p) {
if (*p == ' ')
@ -202,6 +238,7 @@ void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your,
} else {
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 %u 2 h 3 \"%.8s/%.4s\"", m_cols - 1, my1, my2);
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 %u 3 h 3 \"%s%s\"", m_cols - 1, m_displayBuffer1, m_displayBuffer2);
socketPrintf(m_socketfd, "output 128"); // Set LED4 color red
}
m_dmr = false;
@ -214,8 +251,11 @@ void CLCDproc::clearDStarInt()
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 Listening");
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 8"); // Set LED4 color green
}
// LED 1 Green 1 Red 16 Yellow 17
void CLCDproc::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{
assert(type != NULL);
@ -228,7 +268,6 @@ void CLCDproc::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
if (m_duplex) {
if (m_rows > 2U)
socketPrintf(m_socketfd, "widget_set DMR Mode 1 1 DMR");
if (slotNo == 1U)
socketPrintf(m_socketfd, "widget_set DMR Slot2 3 %u %u %u h 3 \"Listening\"", m_rows / 2 + 1, m_cols - 1, m_rows / 2 + 1);
else
@ -236,14 +275,14 @@ void CLCDproc::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
} else {
socketPrintf(m_socketfd, "widget_set DMR Slot1_ 1 %u \"\"", m_rows / 2);
socketPrintf(m_socketfd, "widget_set DMR Slot2_ 1 %u \"\"", m_rows / 2 + 1);
socketPrintf(m_socketfd, "widget_set DMR Slot1 1 %u %u %u h 3 \"Listening\"", m_rows / 2, m_cols - 1, m_rows / 2);
socketPrintf(m_socketfd, "widget_set DMR Slot2 1 %u %u %u h 3 \"\"", m_rows / 2 + 1, m_cols - 1, m_rows / 2 + 1);
}
}
if (m_duplex) {
if (m_rows > 2U)
if (m_rows > 2U)
socketPrintf(m_socketfd, "widget_set DMR Mode 1 1 DMR");
if (slotNo == 1U)
@ -260,7 +299,7 @@ void CLCDproc::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
socketPrintf(m_socketfd, "widget_set DMR Slot2 1 3 %u 3 h 3 \"%s%s\"", m_cols - 1, group ? "TG" : "", dst.c_str());
}
}
socketPrintf(m_socketfd, "output 16"); // Set LED1 color red
m_dmr = true;
}
@ -277,8 +316,11 @@ void CLCDproc::clearDMRInt(unsigned int slotNo)
socketPrintf(m_socketfd, "widget_set DMR Slot1 1 2 15 2 h 3 Listening");
socketPrintf(m_socketfd, "widget_set DMR Slot2 1 3 15 3 h 3 \"\"");
}
socketPrintf(m_socketfd, "output 1"); // Set LED1 color green
}
// LED 3 Green 4 Red 64 Yellow 68
void CLCDproc::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
{
assert(source != NULL);
@ -296,6 +338,7 @@ void CLCDproc::writeFusionInt(const char* source, const char* dest, const char*
} else {
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s >\"", source);
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"%s%u\"", dest);
socketPrintf(m_socketfd, "output 64"); // Set LED3 color red
}
m_dmr = false;
@ -308,8 +351,11 @@ void CLCDproc::clearFusionInt()
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 Listening");
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 4"); // Set LED3 color green
}
// LED 2 Green 2 Red 32 Yellow 34
void CLCDproc::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
@ -325,6 +371,7 @@ void CLCDproc::writeP25Int(const char* source, bool group, unsigned int dest, co
} else {
socketPrintf(m_socketfd, "widget_set P25 Line2 1 2 15 2 h 3 \"%.10s >\"", source);
socketPrintf(m_socketfd, "widget_set P25 Line3 1 3 15 3 h 3 \"%s%u\"", group ? "TG" : "", dest);
socketPrintf(m_socketfd, "output 32"); // Set LED2 color red
}
m_dmr = false;
@ -337,6 +384,7 @@ void CLCDproc::clearP25Int()
socketPrintf(m_socketfd, "widget_set P25 Line3 1 2 15 2 h 3 Listening");
socketPrintf(m_socketfd, "widget_set P25 Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set P25 Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 2"); // Set LED2 color green
}
void CLCDproc::writeCWInt()
@ -351,7 +399,7 @@ void CLCDproc::clockInt(unsigned int ms)
{
m_clockDisplayTimer.clock(ms);
// Idle clock display
// Idle clock display
if (m_displayClock && m_clockDisplayTimer.isRunning() && m_clockDisplayTimer.hasExpired()) {
time_t currentTime;
struct tm *Time;
@ -361,7 +409,7 @@ void CLCDproc::clockInt(unsigned int ms)
Time = gmtime(&currentTime);
else
Time = localtime(&currentTime);
setlocale(LC_TIME, "");
strftime(m_displayBuffer1, 128, "%X", Time); // Time
strftime(m_displayBuffer2, 128, "%x", Time); // Date
@ -377,7 +425,7 @@ void CLCDproc::clockInt(unsigned int ms)
}
// We must set all this information on each select we do
FD_ZERO(&m_readfds); // empty readfds
FD_ZERO(&m_readfds); // empty readfds
// Then we put all the descriptors we want to wait for in a mask = m_readfds
FD_SET(m_socketfd, &m_readfds);
@ -386,12 +434,12 @@ void CLCDproc::clockInt(unsigned int ms)
m_timeout.tv_sec = 0;
m_timeout.tv_usec = 0;
/* The first parameter is the biggest descriptor + 1. The first one was 0, so
/* The first parameter is the biggest descriptor + 1. The first one was 0, so
* every other descriptor will be bigger
*
* readfds = &m_readfds
* writefds = we are not waiting for writefds
* exceptfds = we are not waiting for exception fds
* exceptfds = we are not waiting for exception fds
*/
if (select(m_socketfd + 1, &m_readfds, NULL, NULL, &m_timeout) == -1)

View file

@ -191,7 +191,7 @@ int CMMDVMHost::run()
::close(STDIN_FILENO);
::close(STDOUT_FILENO);
::close(STDERR_FILENO);
#if !defined(HD44780)
#if !defined(HD44780) && !defined(OLED)
//If we are currently root...
if (getuid() == 0) {
struct passwd* user = ::getpwnam("mmdvm");
@ -334,11 +334,11 @@ int CMMDVMHost::run()
unsigned int id = m_conf.getDMRId();
unsigned int colorCode = m_conf.getDMRColorCode();
bool selfOnly = m_conf.getDMRSelfOnly();
bool TGRewriteSlot1 = m_conf.getDMRTGRewriteSlot1();
bool TGRewriteSlot2 = m_conf.getDMRTGRewriteSlot2();
bool BMAutoRewrite = m_conf.getDMRBMAutoRewrite();
bool BMRewriteReflectorVoicePrompts = m_conf.getDMRBMRewriteReflectorVoicePrompts();
std::vector<unsigned int> prefixes = m_conf.getDMRPrefixes();
bool tgRewriteSlot1 = m_conf.getDMRTGRewriteSlot1();
bool tgRewriteSlot2 = m_conf.getDMRTGRewriteSlot2();
bool bmAutoRewrite = m_conf.getDMRBMAutoRewrite();
bool bmRewriteReflectorVoicePrompts = m_conf.getDMRBMRewriteReflectorVoicePrompts();
std::vector<unsigned int> prefixes = m_conf.getDMRPrefixes();
std::vector<unsigned int> blackList = m_conf.getDMRBlackList();
std::vector<unsigned int> dstIDBlackListSlot1RF = m_conf.getDMRDstIdBlacklistSlot1RF();
std::vector<unsigned int> dstIDBlackListSlot2RF = m_conf.getDMRDstIdBlacklistSlot2RF();
@ -395,17 +395,16 @@ int CMMDVMHost::run()
LogInfo(" RSSI Offset: %d", rssiOffset);
}
if (TGRewriteSlot1)
if (tgRewriteSlot1)
LogInfo(" TG Rewrite Slot 1 enabled");
if (TGRewriteSlot2)
if (tgRewriteSlot2)
LogInfo(" TG Rewrite Slot 2 enabled");
if (BMAutoRewrite)
if (bmAutoRewrite)
LogInfo(" BrandMeister Auto Rewrite enabled");
if (BMRewriteReflectorVoicePrompts)
if (bmRewriteReflectorVoicePrompts)
LogInfo(" BrandMeister Rewrite Reflector Voice Prompts enabled");
dmr = new CDMRControl(id, colorCode, callHang, selfOnly, prefixes, blackList,dstIDBlackListSlot1RF,dstIDWhiteListSlot1RF, dstIDBlackListSlot2RF, dstIDWhiteListSlot2RF, dstIDBlackListSlot1NET,dstIDWhiteListSlot1NET, dstIDBlackListSlot2NET, dstIDWhiteListSlot2NET, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, m_lookup, rssiMultiplier, rssiOffset, jitter, TGRewriteSlot1, TGRewriteSlot2, BMAutoRewrite, BMRewriteReflectorVoicePrompts);
dmr = new CDMRControl(id, colorCode, callHang, selfOnly, prefixes, blackList, dstIDBlackListSlot1RF, dstIDWhiteListSlot1RF, dstIDBlackListSlot2RF, dstIDWhiteListSlot2RF, dstIDBlackListSlot1NET,dstIDWhiteListSlot1NET, dstIDBlackListSlot2NET, dstIDWhiteListSlot2NET, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, m_lookup, rssiMultiplier, rssiOffset, jitter, tgRewriteSlot1, tgRewriteSlot2, bmAutoRewrite, bmRewriteReflectorVoicePrompts);
m_dmrTXTimer.setTimeout(txHang);
}
@ -453,6 +452,8 @@ int CMMDVMHost::run()
if (m_ump != NULL) {
bool tx = m_modem->hasTX();
m_ump->setTX(tx);
bool cd = m_modem->hasCD();
m_ump->setCD(cd);
}
unsigned char data[200U];

View file

@ -128,6 +128,7 @@ m_dmrSpace2(0U),
m_ysfSpace(0U),
m_p25Space(0U),
m_tx(false),
m_cd(false),
m_lockout(false),
m_error(false),
m_hwType(HWT_UNKNOWN)
@ -421,6 +422,7 @@ void CModem::clock(unsigned int ms)
// CUtils::dump(1U, "GET_STATUS", m_buffer, m_length);
m_tx = (m_buffer[5U] & 0x01U) == 0x01U;
m_cd = (m_buffer[5U] & 0x02U) == 0x02U;
bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U;
if (adcOverflow)
@ -447,7 +449,7 @@ void CModem::clock(unsigned int ms)
m_p25Space = m_buffer[10U];
m_inactivityTimer.start();
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u lockout=%d", m_buffer[5U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, int(m_lockout));
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[5U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, int(m_lockout), int(m_cd));
}
break;
@ -852,6 +854,11 @@ bool CModem::hasTX() const
return m_tx;
}
bool CModem::hasCD() const
{
return m_cd;
}
bool CModem::hasLockout() const
{
return m_lockout;

View file

@ -59,6 +59,7 @@ public:
bool hasP25Space() const;
bool hasTX() const;
bool hasCD() const;
bool hasLockout() const;
bool hasError() const;
@ -131,6 +132,7 @@ private:
unsigned int m_ysfSpace;
unsigned int m_p25Space;
bool m_tx;
bool m_cd;
bool m_lockout;
bool m_error;
HW_TYPE m_hwType;

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Nextion/NX3224K024.HMI Normal file

Binary file not shown.

BIN
Nextion/NX3224K024.tft Normal file

Binary file not shown.

BIN
Nextion/NX3224K028.HMI Normal file

Binary file not shown.

BIN
Nextion/NX3224K028.tft Normal file

Binary file not shown.

BIN
Nextion/NX3224T024.HMI Normal file

Binary file not shown.

BIN
Nextion/NX3224T028.HMI Normal file

Binary file not shown.

BIN
Nextion/NX4024K032.HMI Normal file

Binary file not shown.

BIN
Nextion/NX4024K032.tft Normal file

Binary file not shown.

BIN
Nextion/NX4024T032.HMI Normal file

Binary file not shown.

BIN
Nextion/NX4832K035.tft Normal file

Binary file not shown.

BIN
Nextion/NX4832T035.HMI Normal file

Binary file not shown.

66
Nextion/README.md Normal file
View file

@ -0,0 +1,66 @@
# Update Nextion Displays from the Command Line
This directory contains a simple python script which you can use to update the
Nextion displays. All you need is a compiled .tft file which is written to the
display's flash memory. The precompiled .tft files with the MMDVMHost default
layout are to be found in this directory as well.
To update the Nextion display you just need to know the serial port the display
is connected to. It could be /dev/ttyUSBx for USB<->Serial adapters or
/dev/ttyAMA0 for the UART on the Raspberry Pi for example.
# Prerequisites
You need to have python installed as well as the python-serial package. That can
normally be found in your distro's package manager.
# File Naming Convention
There are compiled .tft files in the repo for basic and enhanced Nextion
displays of sizes 2.4", 2.8", 3.2" and 3.5". Please choose depending on the
model number printed on the back of the display.
The basic displays are denoted by a "T" as 7th character in the filename and
model number whereas enhanced displays have a "K" in that position. The actual
display size can be derived from the last two digits. The four digits in between
the characters refert to the diplay's resolution.
For example: A model number NX4832T035 represents a display with:
- a resolution of 320x480 pixels
- basic command set
- a screen size of 3.5"
# Updating the Display
Now comes the easy part. Just execute:
```
$ python nextion.py NX4832T035.tft /dev/ttyUSB0
```
And the output should be as follows:
```
Trying with baudrate: 2400...
Trying with baudrate: 4800...
Trying with baudrate: 9600...
Connected with baudrate: 9600...
Status: comok
Touchscreen: yes
Model: NX4832T035_011R
Firmware version: 68
MCU code: 61488
Serial: D2658880C35D2124
Flash size: 16777216
Downloading, 100%...
File transferred successfully
```
# Known errors
Especially when using USB<->Serial adapters there are cases in which the scripts
stops at different times. This is known and due to the very simple update
protocol. In this case you have to fix the display by using a SD-Card to update
the display. The /dev/ttyAMAx ports do not seems to suffer from this issue.

View file

@ -36,10 +36,15 @@ def getBaudrate(ser, fSize=None, checkModel=None):
if 'comok' in r:
print 'Connected with baudrate: ' + str(baudrate) + '...'
noConnect = False
status, unknown1, model, unknown2, version, serial, flashSize = r.strip("\xff\x00").split(',')
print 'Status: ' + status
status, unknown1, model, fwversion, mcucode, serial, flashSize = r.strip("\xff\x00").split(',')
print 'Status: ' + status.split(' ')[0]
if status.split(' ')[1] == "1":
print 'Touchscreen: yes'
else:
print 'Touchscreen: no'
print 'Model: ' + model
print 'Version: ' + version
print 'Firmware version: ' + fwversion
print 'MCU code: ' + mcucode
print 'Serial: ' + serial
print 'Flash size: ' + flashSize
if fSize and fSize > flashSize:
@ -80,23 +85,26 @@ def transferFile(ser, filename, fSize):
if "\x05" in r:
continue
else:
print
return False
break
print
return True
def upload(ser, filename, checkModel=None):
if not getBaudrate(ser, os.path.getsize(filename), checkModel):
print 'could not find baudrate'
print 'Could not find baudrate'
exit(1)
if not setDownloadBaudrate(ser, os.path.getsize(filename), 115200):
print 'could not set download baudrate'
print 'Could not set download baudrate'
exit(1)
if not transferFile(ser, filename, os.path.getsize(filename)):
print 'could not transfer file'
print 'Could not transfer file'
exit(1)
print 'File transferred successfully'
exit(0)
if __name__ == "__main__":
@ -111,7 +119,7 @@ if __name__ == "__main__":
except serial.serialutil.SerialException:
print 'could not open serial device ' + sys.argv[2]
exit(1)
if (serial.VERSION <= "3.0"):
if serial.VERSION <= "3.0":
if not ser.isOpen():
ser.open()
else:

View file

@ -56,6 +56,26 @@ static unsigned char logo_dmr_bmp[] =
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111
};
//D-Star 64x16 px
static unsigned char logo_dstar_bmp[] =
{ 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b10000001, 0b11111100, 0b00000000, 0b00111100, 0b00000000, 0b00000000, 0b00000000, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b01000010, 0b01000000, 0b00000000, 0b00000000, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b01000000, 0b01000000, 0b00000000, 0b00000000, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b01000000, 0b01000000, 0b00000000, 0b00000000, 0b01000001,
0b10000001, 0b00000010, 0b01111111, 0b00111100, 0b01111000, 0b00111100, 0b00111100, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b00000010, 0b01000010, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b00111110, 0b01000000, 0b01000001,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b01000010, 0b01000000, 0b00000001,
0b10000001, 0b00000010, 0b00000000, 0b01000010, 0b01000010, 0b01000010, 0b01000000, 0b01000001,
0b10000001, 0b11111100, 0b00000000, 0b00111100, 0b00111100, 0b00111100, 0b01000000, 0b01000001,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111
};
COLED::COLED(unsigned char displayType, unsigned char displayBrightness, bool displayInvert) :
m_displayType(displayType),
m_displayBrightness(displayBrightness),
@ -108,7 +128,7 @@ void COLED::setIdleInt()
display.clearDisplay();
OLED_statusbar();
display.setCursor(0,display.height()/2);
display.setTextSize(3);
display.setTextSize(2);
display.print("Idle");
display.setTextSize(1);
display.display();
@ -286,7 +306,7 @@ void COLED::clearCWInt()
{
display.clearDisplay();
display.setCursor(0,display.height()/2);
display.setTextSize(3);
display.setTextSize(2);
display.print("Idle");
display.setTextSize(1);
display.display();
@ -307,7 +327,7 @@ void COLED::OLED_statusbar()
if (m_mode == MODE_DMR)
display.drawBitmap(0, 0, logo_dmr_bmp, 48, 16, WHITE);
else if (m_mode == MODE_DSTAR)
display.print("D-Star");
display.drawBitmap(0, 0, logo_dstar_bmp, 64, 16, WHITE);
else if (m_mode == MODE_YSF)
display.print("Fusion");
else if (m_mode == MODE_P25)

View file

@ -6,11 +6,49 @@ http://wiringpi.com/download-and-install/ which must be installed in all cases.
The HD44780 in 4-bit mode is probably the most common connection method and
wiring details can be found at http://wiringpi.com/dev-lib/lcd-library/
The setup that is commonly used for MMDVM is the 4-bit connection that is also
documented within wiringPi. The HD44780 displays have a standardized 16-pin
connector (14 pins if without backlight). The pin numbers on HD44780 refer to
this standard numbering.
The pin numbers on Raspberry Pi side are the physical pin numbers of the GPIO
pin header, in brackets the wiringPi pin number as these are referred to in the
MMDVM.ini file.
The wiring ist as follows:
HD44780 pin Raspberry Pi GPIO
GND 1 -------- 6 GND
VCC 2 -------- 2 +5V
V0 3 -------- Trimmer between +5V and GND for contrast
RS 4 -------- 26 CE1 (11)
RW 5 -------- 6 GND
E 6 -------- 24 CE0 (10)
D0 7
D1 8
D2 9
D3 10
D4 11 -------- 11 GPIO0 (0)
D5 12 -------- 12 GPIO1 (1)
D6 13 -------- 13 GPIO2 (2)
D7 14 -------- 15 GPIO3 (3)
GND 15 -------- 6 GND
VCC 16 -------- 2 +5V
The relevant part in the MMDVM.ini is like outlined below.
[HD44780]
Rows=4
Columns=20
# For basic HD44780 displays (4-bit connection)
# rs, strb, d0, d1, d2, d3
Pins=11,10,0,1,2,3
To compile MMDVMHost with support for the HD44780 use the following commands.
# cp Makefile.Pi.HD44780 Makefile
# make clean
# make
# make -f Makefile.Pi.HD44780
Other HD44780 variations exist that connect via I2C. Support is also via
wiringPi, but to compile for each I2C device requires a different Makefile

23
UMP.cpp
View file

@ -31,6 +31,7 @@ const unsigned char UMP_HELLO = 0x00U;
const unsigned char UMP_SET_MODE = 0x01U;
const unsigned char UMP_SET_TX = 0x02U;
const unsigned char UMP_SET_CD = 0x03U;
const unsigned char UMP_WRITE_SERIAL = 0x10U;
const unsigned char UMP_READ_SERIAL = 0x11U;
@ -47,7 +48,8 @@ m_length(0U),
m_offset(0U),
m_lockout(false),
m_mode(MODE_IDLE),
m_tx(false)
m_tx(false),
m_cd(false)
{
m_buffer = new unsigned char[BUFFER_LENGTH];
}
@ -125,6 +127,25 @@ bool CUMP::setTX(bool on)
return m_serial.write(buffer, 4U) == 4;
}
bool CUMP::setCD(bool on)
{
if (on == m_cd)
return true;
m_cd = on;
unsigned char buffer[4U];
buffer[0U] = UMP_FRAME_START;
buffer[1U] = 4U;
buffer[2U] = UMP_SET_CD;
buffer[3U] = on ? 0x01U : 0x00U;
// CUtils::dump(1U, "Transmitted", buffer, 4U);
return m_serial.write(buffer, 4U) == 4;
}
bool CUMP::getLockout() const
{
return m_lockout;

3
UMP.h
View file

@ -36,6 +36,8 @@ public:
bool setTX(bool on);
bool setCD(bool on);
bool getLockout() const;
virtual int read(unsigned char* buffer, unsigned int length);
@ -55,6 +57,7 @@ private:
bool m_lockout;
unsigned char m_mode;
bool m_tx;
bool m_cd;
};
#endif

View file

@ -20,20 +20,36 @@
#define PIN_LED 13
#endif
#if defined(__MK20DX256__)
#define PIN_DSTAR 2
#define PIN_DMR 3
#define PIN_DMR 3
#define PIN_YSF 4
#define PIN_P25 5
#define PIN_TX 10
#define PIN_CD 11
#define PIN_LOCKOUT 12
#else
#define PIN_DSTAR 2
#define PIN_DMR 3
#define PIN_YSF 4
#define PIN_P25 5
#define PIN_TX 6
#define PIN_CD 7
#define PIN_LOCKOUT 7
#define PIN_LOCKOUT 8
#endif
// Use the LOCKOUT function on the UMP
// #define USE_LOCKOUT
void setup()
{
Serial.begin(115200);
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) || defined(__MK20DX256__)
Serial1.begin(9600);
#endif
@ -43,6 +59,7 @@ void setup()
pinMode(PIN_YSF, OUTPUT);
pinMode(PIN_P25, OUTPUT);
pinMode(PIN_TX, OUTPUT);
pinMode(PIN_CD, OUTPUT);
pinMode(PIN_LOCKOUT, INPUT);
digitalWrite(PIN_DSTAR, LOW);
@ -50,6 +67,7 @@ void setup()
digitalWrite(PIN_YSF, LOW);
digitalWrite(PIN_P25, LOW);
digitalWrite(PIN_TX, LOW);
digitalWrite(PIN_CD, LOW);
}
#define UMP_FRAME_START 0xF0U
@ -58,6 +76,7 @@ void setup()
#define UMP_SET_MODE 0x01U
#define UMP_SET_TX 0x02U
#define UMP_SET_CD 0x03U
#define UMP_WRITE_SERIAL 0x10U
@ -110,7 +129,10 @@ void loop()
case UMP_SET_TX:
digitalWrite(PIN_TX, m_buffer[3U] == 0x01U ? HIGH : LOW);
break;
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__)
case UMP_SET_CD:
digitalWrite(PIN_CD, m_buffer[3U] == 0x01U ? HIGH : LOW);
break;
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) || defined(__MK20DX256__)
case UMP_WRITE_SERIAL:
Serial1.write(m_buffer + 3U, m_length - 3U);
break;
@ -125,7 +147,10 @@ void loop()
}
}
bool lockout = digitalRead(PIN_LOCKOUT) == HIGH;
bool lockout = false;
#if defined(USE_LOCKOUT)
lockout = digitalRead(PIN_LOCKOUT) == HIGH;
#endif
if (lockout != m_lockout) {
uint8_t data[4U];
data[0U] = UMP_FRAME_START;
@ -137,7 +162,7 @@ void loop()
m_lockout = lockout;
}
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) || defined(__MK20DX256__)
while (Serial1.available())
Serial1.read();
#endif
@ -157,4 +182,3 @@ void loop()
}
}
}