add support to transmit commands from sysview;

pull/72/head
Bryan Biedenkapp 1 year ago
parent e9d4039ce0
commit aab5e208e4

@ -0,0 +1,239 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DynRegroupSubscriberWnd.h
* @ingroup fneSysView
*/
#if !defined(__DYN_REGROUP_SUBSCRIBER_WND_H__)
#define __DYN_REGROUP_SUBSCRIBER_WND_H__
#include "TransmitWndBase.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the line edit control for TGIDs.
* @ingroup tged
*/
class HOST_SW_API TGIdLineEdit final : public FLineEdit {
public:
/**
* @brief Initializes a new instance of the TGIdLineEdit class.
* @param widget
*/
explicit TGIdLineEdit(FWidget* widget = nullptr) : FLineEdit{widget}
{
setInputFilter("[[:digit:]]");
}
/*
** Event Handlers
*/
/**
* @brief Event that occurs on keyboard key press.
* @param e Keyboard Event.
*/
void onKeyPress(finalcut::FKeyEvent* e) override
{
const auto key = e->key();
if (key == FKey::Up) {
emitCallback("up-pressed");
e->accept();
return;
} else if (key == FKey::Down) {
emitCallback("down-pressed");
e->accept();
return;
}
FLineEdit::onKeyPress(e);
}
};
/**
* @brief This class implements the dynamic regroup subscriber window.
* @ingroup fneSysView
*/
class HOST_SW_API DynRegroupSubscriberWnd final : public TransmitWndBase {
public:
/**
* @brief Initializes a new instance of the DynRegroupSubscriberWnd class.
* @param widget
*/
explicit DynRegroupSubscriberWnd(FWidget* widget = nullptr) : TransmitWndBase{widget}
{
/* stub */
}
/**
* @brief Flag indicating a dynamic regroup lock operation should be performed.
*/
bool lock;
/**
* @brief Flag indicating a dynamic regroup unlock operation should be performed.
*/
bool unlock;
private:
FLabel m_dialogLabel{"Dynamic Regroup Subscriber", this};
FLabel m_subscriberLabel{"Subscriber ID: ", this};
FSpinBox m_subscriber{this};
FLabel m_tgLabel{"Talkgroup ID: ", this};
TGIdLineEdit m_tgId{this};
uint32_t m_selectedTgId = 1U;
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setText("Dynamic Regroup Subscriber");
FDialog::setSize(FSize{60, 17});
TransmitWndBase::initLayout();
m_dmrSlotLabel.setVisible(false);
m_dmrSlot.setDisable();
m_dmrSlot.setVisible(false);
m_mode = modem::STATE_P25;
m_digModeGroup.setVisible(false);
m_modeDMR.setDisable();
m_modeDMR.setVisible(false);
m_modeP25.setDisable();
m_modeP25.setVisible(false);
redraw();
focusFirstChild();
}
/**
* @brief Initializes window controls.
*/
void initControls() override
{
TransmitWndBase::initControls();
// subscriber entry
{
m_dialogLabel.setGeometry(FPoint(6, 6), FSize(35, 2));
if (lock)
m_dialogLabel.setText("Dynamic Regroup - Lock");
if (unlock)
m_dialogLabel.setText("Dynamic Regroup - Unlock");
m_dialogLabel.setEmphasis();
m_dialogLabel.setAlignment(Align::Center);
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
m_subscriber.setRange(0, 16777211);
m_subscriber.setValue(1);
m_subscriber.setShadow(false);
m_subscriber.addCallback("changed", [&]() {
if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) {
m_txButton.setEnable(true);
}
else {
m_txButton.setEnable(false);
}
redraw();
});
m_tgLabel.setGeometry(FPoint(2, 9), FSize(25, 1));
m_tgId.setGeometry(FPoint(28, 9), FSize(20, 1));
m_tgId.setAlignment(finalcut::Align::Right);
m_tgId.setText("1");
m_tgId.setShadow(false);
m_tgId.addCallback("up-pressed", [&]() {
uint32_t tgId = ::atoi(m_tgId.getText().c_str());
tgId++;
if (tgId > 16777215U) {
tgId = 16777215U;
}
m_tgId.setText(std::to_string(tgId));
redraw();
});
m_tgId.addCallback("down-pressed", [&]() {
uint32_t tgId = ::atoi(m_tgId.getText().c_str());
tgId--;
if (tgId < 1U) {
tgId = 1U;
}
m_tgId.setText(std::to_string(tgId));
redraw();
});
m_tgId.addCallback("changed", [&]() {
uint32_t tgId = ::atoi(m_tgId.getText().c_str());
if (tgId < 1U) {
tgId = 1U;
}
if (tgId > 16777215U) {
tgId = 16777215U;
}
m_tgId.setText(std::to_string(tgId));
m_selectedTgId = tgId;
});
if (lock || unlock) {
m_tgId.setDisable();
}
}
m_dialogLabel.redraw();
m_subscriberLabel.redraw();
redraw();
}
/**
* @brief Helper to transmit.
*/
void setTransmit() override
{
switch (m_mode) {
case modem::STATE_P25:
{
using namespace p25;
using namespace p25::defines;
if (lock) {
writeP25_Ext_Func(ExtendedFunctions::DYN_REGRP_LOCK, WUID_FNE, (uint32_t)m_subscriber.getValue());
break;
}
if (unlock) {
writeP25_Ext_Func(ExtendedFunctions::DYN_REGRP_UNLOCK, WUID_FNE, (uint32_t)m_subscriber.getValue());
break;
}
writeP25_Ext_Func(ExtendedFunctions::DYN_REGRP_REQ, m_selectedTgId, (uint32_t)m_subscriber.getValue());
}
break;
default:
break;
}
}
};
#endif // __DYN_REGROUP_SUBSCRIBER_WND_H__

@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file InhibitSubscriberWnd.h
* @ingroup fneSysView
*/
#if !defined(__INHIBIT_SUBSCRIBER_WND_H__)
#define __INHIBIT_SUBSCRIBER_WND_H__
#include "TransmitWndBase.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the inhibit subscriber window.
* @ingroup fneSysView
*/
class HOST_SW_API InhibitSubscriberWnd final : public TransmitWndBase {
public:
/**
* @brief Initializes a new instance of the InhibitSubscriberWnd class.
* @param channel Channel data.
* @param widget
*/
explicit InhibitSubscriberWnd(FWidget* widget = nullptr) : TransmitWndBase{widget}
{
/* stub */
}
private:
FLabel m_dialogLabel{"Inhibit Subscriber", this};
FLabel m_subscriberLabel{"Subscriber ID: ", this};
FSpinBox m_subscriber{this};
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setText("Inhibit Subscriber");
FDialog::setSize(FSize{60, 16});
TransmitWndBase::initLayout();
}
/**
* @brief Initializes window controls.
*/
void initControls() override
{
TransmitWndBase::initControls();
// subscriber entry
{
m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2));
m_dialogLabel.setEmphasis();
m_dialogLabel.setAlignment(Align::Center);
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
m_subscriber.setRange(0, 16777211);
m_subscriber.setValue(1);
m_subscriber.setShadow(false);
m_subscriber.addCallback("changed", [&]() {
if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) {
m_txButton.setEnable(true);
}
else {
m_txButton.setEnable(false);
}
redraw();
});
}
m_dialogLabel.redraw();
m_subscriberLabel.redraw();
redraw();
}
/**
* @brief Helper to transmit.
*/
void setTransmit() override
{
switch (m_mode) {
case modem::STATE_DMR:
{
using namespace dmr;
using namespace dmr::defines;
writeDMR_Ext_Func((uint8_t)m_dmrSlot.getValue(), ExtendedFunctions::INHIBIT, WUID_STUNI,
(uint32_t)m_subscriber.getValue());
}
break;
case modem::STATE_P25:
{
using namespace p25;
using namespace p25::defines;
writeP25_Ext_Func(ExtendedFunctions::INHIBIT, WUID_FNE, (uint32_t)m_subscriber.getValue());
}
break;
default:
break;
}
}
};
#endif // __INHIBIT_SUBSCRIBER_WND_H__

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file PageSubscriberWnd.h
* @ingroup fneSysView
*/
#if !defined(__PAGE_SUBSCRIBER_WND_H__)
#define __PAGE_SUBSCRIBER_WND_H__
#include "TransmitWndBase.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the page subscriber window.
* @ingroup fneSysView
*/
class HOST_SW_API PageSubscriberWnd final : public TransmitWndBase {
public:
/**
* @brief Initializes a new instance of the PageSubscriberWnd class.
* @param widget
*/
explicit PageSubscriberWnd(FWidget* widget = nullptr) : TransmitWndBase{widget}
{
/* stub */
}
private:
FLabel m_dialogLabel{"Page Subscriber", this};
FLabel m_subscriberLabel{"Subscriber ID: ", this};
FSpinBox m_subscriber{this};
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setText("Page Subscriber");
FDialog::setSize(FSize{60, 16});
TransmitWndBase::initLayout();
}
/**
* @brief Initializes window controls.
*/
void initControls() override
{
TransmitWndBase::initControls();
// subscriber entry
{
m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2));
m_dialogLabel.setEmphasis();
m_dialogLabel.setAlignment(Align::Center);
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
m_subscriber.setRange(0, 16777211);
m_subscriber.setValue(1);
m_subscriber.setShadow(false);
m_subscriber.addCallback("changed", [&]() {
if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) {
m_txButton.setEnable(true);
}
else {
m_txButton.setEnable(false);
}
redraw();
});
}
m_dialogLabel.redraw();
m_subscriberLabel.redraw();
redraw();
}
/**
* @brief Helper to transmit.
*/
void setTransmit() override
{
switch (m_mode) {
case modem::STATE_DMR:
{
using namespace dmr;
using namespace dmr::lc::csbk;
std::unique_ptr<CSBK_CALL_ALRT> csbk = std::make_unique<CSBK_CALL_ALRT>();
csbk->setGI(false);
csbk->setSrcId(DMRDEF::WUID_ALL);
csbk->setDstId((uint32_t)m_subscriber.getValue());
write_CSBK((uint8_t)m_dmrSlot.getValue(), csbk.get());
}
break;
case modem::STATE_P25:
{
using namespace p25;
using namespace p25::lc::tsbk;
std::unique_ptr<IOSP_CALL_ALRT> iosp = std::make_unique<IOSP_CALL_ALRT>();
iosp->setSrcId(P25DEF::WUID_FNE);
iosp->setDstId((uint32_t)m_subscriber.getValue());
write_TSDU(iosp.get());
}
break;
default:
break;
}
}
};
#endif // __PAGE_SUBSCRIBER_WND_H__

@ -0,0 +1,124 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file RadioCheckSubscriberWnd.h
* @ingroup fneSysView
*/
#if !defined(__RADIO_CHECK_SUBSCRIBER_WND_H__)
#define __RADIO_CHECK_SUBSCRIBER_WND_H__
#include "TransmitWndBase.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the radio check subscriber window.
* @ingroup fneSysView
*/
class HOST_SW_API RadioCheckSubscriberWnd final : public TransmitWndBase {
public:
/**
* @brief Initializes a new instance of the RadioCheckSubscriberWnd class.
* @param widget
*/
explicit RadioCheckSubscriberWnd(FWidget* widget = nullptr) : TransmitWndBase{widget}
{
/* stub */
}
private:
FLabel m_dialogLabel{"Radio Check Subscriber", this};
FLabel m_subscriberLabel{"Subscriber ID: ", this};
FSpinBox m_subscriber{this};
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setText("Radio Check Subscriber");
FDialog::setSize(FSize{60, 16});
TransmitWndBase::initLayout();
}
/**
* @brief Initializes window controls.
*/
void initControls() override
{
TransmitWndBase::initControls();
// subscriber entry
{
m_dialogLabel.setGeometry(FPoint(6, 6), FSize(25, 2));
m_dialogLabel.setEmphasis();
m_dialogLabel.setAlignment(Align::Center);
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
m_subscriber.setRange(0, 16777211);
m_subscriber.setValue(1);
m_subscriber.setShadow(false);
m_subscriber.addCallback("changed", [&]() {
if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) {
m_txButton.setEnable(true);
}
else {
m_txButton.setEnable(false);
}
redraw();
});
}
m_dialogLabel.redraw();
m_subscriberLabel.redraw();
redraw();
}
/**
* @brief Helper to transmit.
*/
void setTransmit() override
{
switch (m_mode) {
case modem::STATE_DMR:
{
using namespace dmr;
using namespace dmr::defines;
writeDMR_Ext_Func((uint8_t)m_dmrSlot.getValue(), ExtendedFunctions::CHECK, WUID_STUNI,
(uint32_t)m_subscriber.getValue());
}
break;
case modem::STATE_P25:
{
using namespace p25;
using namespace p25::defines;
writeP25_Ext_Func(ExtendedFunctions::CHECK, WUID_FNE, (uint32_t)m_subscriber.getValue());
}
break;
default:
break;
}
}
};
#endif // __RADIO_CHECK_SUBSCRIBER_WND_H__

@ -136,6 +136,15 @@ void closePeerNetwork()
g_app->closePeerNetwork();
}
/**
* @brief
*/
network::PeerNetwork* getNetwork()
{
if (g_app != nullptr)
return g_app->network;
}
/* Helper to pring usage the command line arguments. (And optionally an error.) */
void usage(const char* message, const char* arg)

@ -21,6 +21,7 @@
#include "common/lookups/TalkgroupRulesLookup.h"
#include "common/lookups/IdenTableLookup.h"
#include "common/yaml/Yaml.h"
#include "network/PeerNetwork.h"
#include <string>
@ -94,4 +95,10 @@ extern HOST_SW_API bool createPeerNetwork();
*/
extern HOST_SW_API void closePeerNetwork();
/**
* @brief
* @returns PeerNetwork*
*/
extern HOST_SW_API network::PeerNetwork* getNetwork();
#endif // __SYS_VIEW_MAIN_H__

@ -29,6 +29,12 @@ using namespace finalcut;
#include "LogDisplayWnd.h"
#include "PageSubscriberWnd.h"
#include "InhibitSubscriberWnd.h"
#include "UninhibitSubscriberWnd.h"
#include "RadioCheckSubscriberWnd.h"
#include "DynRegroupSubscriberWnd.h"
#include <vector>
// ---------------------------------------------------------------------------
@ -61,6 +67,52 @@ public:
m_quitItem.addCallback("clicked", getFApplication(), &FApplication::cb_exitApp, this);
m_keyF3.addCallback("activate", getFApplication(), &FApplication::cb_exitApp, this);
// command menu
m_pageSU.addCallback("clicked", this, [&]() {
PageSubscriberWnd wnd{this};
wnd.show();
});
m_keyF5.addCallback("activate", this, [&]() {
PageSubscriberWnd wnd{this};
wnd.show();
});
m_radioCheckSU.addCallback("clicked", this, [&]() {
RadioCheckSubscriberWnd wnd{this};
wnd.show();
});
m_cmdMenuSeparator1.setSeparator();
m_inhibitSU.addCallback("clicked", this, [&]() {
InhibitSubscriberWnd wnd{this};
wnd.show();
});
m_keyF7.addCallback("activate", this, [&]() {
InhibitSubscriberWnd wnd{this};
wnd.show();
});
m_uninhibitSU.addCallback("clicked", this, [&]() {
UninhibitSubscriberWnd wnd{this};
wnd.show();
});
m_keyF8.addCallback("activate", this, [&]() {
UninhibitSubscriberWnd wnd{this};
wnd.show();
});
m_cmdMenuSeparator2.setSeparator();
m_dynRegrp.addCallback("clicked", this, [&]() {
DynRegroupSubscriberWnd wnd{this};
wnd.show();
});
m_dynRegrpLck.addCallback("clicked", this, [&]() {
DynRegroupSubscriberWnd wnd{this};
wnd.lock = true;
wnd.show();
});
m_dynRegrpUnlock.addCallback("clicked", this, [&]() {
DynRegroupSubscriberWnd wnd{this};
wnd.unlock = true;
wnd.show();
});
// help menu
m_aboutItem.addCallback("clicked", this, [&]() {
const FString line(2, UniChar::BoxDrawingsHorizontal);
@ -89,11 +141,25 @@ private:
FMenu m_fileMenu{"&File", &m_menuBar};
FMenuItem m_quitItem{"&Quit", &m_fileMenu};
FMenu m_cmdMenu{"&Commands", &m_menuBar};
FMenuItem m_pageSU{"&Page Subscriber", &m_cmdMenu};
FMenuItem m_radioCheckSU{"Radio &Check Subscriber", &m_cmdMenu};
FMenuItem m_cmdMenuSeparator1{&m_cmdMenu};
FMenuItem m_inhibitSU{"&Inhibit Subscriber", &m_cmdMenu};
FMenuItem m_uninhibitSU{"&Uninhibit Subscriber", &m_cmdMenu};
FMenuItem m_cmdMenuSeparator2{&m_cmdMenu};
FMenuItem m_dynRegrp{"&Dynamic Regroup", &m_cmdMenu};
FMenuItem m_dynRegrpLck{"Dynamic Regroup - Lock", &m_cmdMenu};
FMenuItem m_dynRegrpUnlock{"Dynamic Regroup - Unlock", &m_cmdMenu};
FMenu m_helpMenu{"&Help", &m_menuBar};
FMenuItem m_aboutItem{"&About", &m_helpMenu};
FStatusBar m_statusBar{this};
FStatusKey m_keyF3{FKey::F3, "Quit", &m_statusBar};
FStatusKey m_keyF5{FKey::F5, "Page Subscriber", &m_statusBar};
FStatusKey m_keyF7{FKey::F7, "Inhibit Subscriber", &m_statusBar};
FStatusKey m_keyF8{FKey::F8, "Uninhibit Subscriber", &m_statusBar};
/*
** Event Handlers

@ -0,0 +1,342 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file TransmitWndBase.h
* @ingroup fneSysView
*/
#if !defined(__TRANSMIT_WND_BASE_H__)
#define __TRANSMIT_WND_BASE_H__
#include "common/lookups/AffiliationLookup.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/CSBK.h"
#include "common/dmr/lc/csbk/CSBKFactory.h"
#include "common/dmr/SlotType.h"
#include "common/dmr/Sync.h"
#include "common/p25/P25Defines.h"
#include "common/p25/lc/LC.h"
#include "common/p25/lc/TSBK.h"
#include "common/p25/lc/tsbk/TSBKFactory.h"
#include "common/p25/Sync.h"
#include "host/modem/Modem.h"
#include "SysViewMain.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the base class for transmit windows.
* @ingroup fneSysView
*/
class HOST_SW_API TransmitWndBase : public finalcut::FDialog {
public:
/**
* @brief Initializes a new instance of the TransmitWndBase class.
* @param widget
*/
explicit TransmitWndBase(FWidget* widget = nullptr) : FDialog{widget}
{
/* stub */
}
protected:
uint8_t m_mode = modem::STATE_DMR;
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setMinimizable(true);
FDialog::setShadow();
std::size_t maxWidth, maxHeight;
const auto& rootWidget = getRootWidget();
if (rootWidget) {
maxWidth = rootWidget->getClientWidth();
maxHeight = rootWidget->getClientHeight();
}
else {
// fallback to xterm default size
maxWidth = 80;
maxHeight = 24;
}
const int x = 1 + int((maxWidth - getWidth()) / 2);
const int y = 1 + int((maxHeight - getHeight()) / 3);
FWindow::setPos(FPoint{x, y}, false);
FDialog::adjustSize();
FDialog::setModal();
initControls();
FDialog::initLayout();
rootWidget->redraw(); // bryanb: wtf?
redraw();
}
/**
* @brief Initializes window controls.
*/
virtual void initControls()
{
resizeControls();
m_dmrSlotLabel.setGeometry(FPoint(2, 4), FSize(10, 1));
m_dmrSlot.setGeometry(FPoint(18, 4), FSize(5, 1));
m_dmrSlot.setRange(1, 2);
m_dmrSlot.setValue(1);
m_dmrSlot.setShadow(false);
m_digModeGroup.setGeometry(FPoint(2, 1), FSize(56, 2));
m_modeDMR.setPos(FPoint(1, 1));
m_modeDMR.addCallback("toggled", [&]() {
if (m_modeDMR.isChecked()) {
m_mode = modem::STATE_DMR;
m_dmrSlot.setEnable(true);
redraw();
}
});
m_modeP25.setPos(FPoint(13, 1));
m_modeP25.addCallback("toggled", [&]() {
if (m_modeP25.isChecked()) {
m_mode = modem::STATE_P25;
m_dmrSlot.setEnable(false);
redraw();
}
});
/*
m_modeNXDN.setPos(FPoint(22, 1));
m_modeNXDN.addCallback("toggled", [&]() {
if (m_modeNXDN.isChecked()) {
m_mode = modem::STATE_NXDN;
m_dmrSlot.setEnable(false);
redraw();
}
});
*/
focusFirstChild();
}
/**
* @brief
*/
void resizeControls()
{
// transmit button and close button logic
m_txButton.setGeometry(FPoint(3, int(getHeight()) - 6), FSize(10, 3));
m_txButton.addCallback("clicked", [&]() { setTransmit(); });
m_closeButton.setGeometry(FPoint(17, int(getHeight()) - 6), FSize(9, 3));
m_closeButton.addCallback("clicked", [&]() { hide(); });
}
/**
* @brief Adjusts window size.
*/
void adjustSize() override
{
FDialog::adjustSize();
}
/*
** Event Handlers
*/
/**
* @brief Event that occurs on keyboard key press.
* @param e Keyboard Event.
*/
void onKeyPress(finalcut::FKeyEvent* e) override
{
const auto key = e->key();
if (key == FKey::F12) {
setTransmit();
}
}
/**
* @brief Event that occurs when the window is closed.
* @param e Close Event
*/
void onClose(FCloseEvent* e) override
{
hide();
}
protected:
/**
* @brief Helper to write a DMR extended function packet.
* @param slot DMR slot number.
* @param func
* @param arg
* @param dstId
*/
void writeDMR_Ext_Func(uint8_t slot, uint32_t func, uint32_t arg, uint32_t dstId)
{
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc::csbk;
std::unique_ptr<CSBK_EXT_FNCT> csbk = std::make_unique<CSBK_EXT_FNCT>();
csbk->setGI(false);
csbk->setExtendedFunction(func);
csbk->setSrcId(arg);
csbk->setDstId(dstId);
LogMessage(LOG_RF, "DMR Slot %u, CSBK, %s, op = $%02X, arg = %u, tgt = %u",
slot, csbk->toString().c_str(), func, arg, dstId);
write_CSBK(slot, csbk.get());
}
/**
* @brief Helper to write a network CSBK.
* @param slot DMR slot number.
* @param csbk Instance of dmr::lc::CSBK.
*/
void write_CSBK(uint8_t slot, dmr::lc::CSBK* csbk)
{
using namespace dmr;
using namespace dmr::defines;
uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES);
SlotType slotType;
slotType.setColorCode(0U);
slotType.setDataType(DataType::CSBK);
// Regenerate the CSBK data
csbk->encode(data + 2U);
// Regenerate the Slot Type
slotType.encode(data + 2U);
// Convert the Data Sync to be from the BS or MS as needed
Sync::addDMRDataSync(data + 2U, true);
data::NetData dmrData;
dmrData.setSlotNo(slot);
dmrData.setDataType(DataType::CSBK);
dmrData.setSrcId(csbk->getSrcId());
dmrData.setDstId(csbk->getDstId());
dmrData.setFLCO(csbk->getGI() ? FLCO::GROUP : FLCO::PRIVATE);
dmrData.setN(0U);
dmrData.setSeqNo(0U);
dmrData.setBER(0U);
dmrData.setRSSI(0U);
dmrData.setData(data + 2U);
getNetwork()->writeDMR(dmrData);
}
/**
* @brief Helper to write a P25 extended function packet.
* @param func
* @param arg
* @param dstId
*/
void writeP25_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId)
{
using namespace p25;
using namespace p25::defines;
using namespace p25::lc::tsbk;
std::unique_ptr<IOSP_EXT_FNCT> iosp = std::make_unique<IOSP_EXT_FNCT>();
iosp->setExtendedFunction(func);
iosp->setSrcId(arg);
iosp->setDstId(dstId);
// class $02 is Motorola -- set the MFID properly
if ((func >> 8) == 0x02U) {
iosp->setMFId(MFG_MOT);
}
LogMessage(LOG_RF, P25_TSDU_STR ", %s, mfId = $%02X, op = $%02X, arg = %u, tgt = %u",
iosp->toString().c_str(), iosp->getMFId(), iosp->getExtendedFunction(), iosp->getSrcId(), iosp->getDstId());
write_TSDU(iosp.get());
}
/**
* @brief Helper to write a network TSDU.
* @param tsbk Instance of p25::lc::TSBK.
*/
void write_TSDU(p25::lc::TSBK* tsbk)
{
using namespace p25;
using namespace p25::defines;
uint8_t data[P25_TSDU_FRAME_LENGTH_BYTES];
::memset(data, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
// Generate Sync
Sync::addP25Sync(data);
// network bursts have no NID
// Generate TSBK block
tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
tsbk->encode(data);
// Add busy bits
P25Utils::addStatusBits(data, P25_TSDU_FRAME_LENGTH_BYTES, false);
// Set first busy bits to 1,1
P25Utils::setStatusBits(data, P25_SS0_START, true, true);
LogDebug(LOG_RF, P25_TSDU_STR ", lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
tsbk->getSysId(), tsbk->getNetId());
Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES, P25_TSBK_FEC_LENGTH_BYTES);
lc::LC lc = lc::LC();
lc.setLCO(tsbk->getLCO());
lc.setMFId(tsbk->getMFId());
lc.setSrcId(tsbk->getSrcId());
lc.setDstId(tsbk->getDstId());
getNetwork()->writeP25TSDU(lc, data);
}
/**
* @brief Helper to transmit.
*/
virtual void setTransmit()
{
/* stub */
}
FButton m_txButton{"Transmit", this};
FButton m_closeButton{"Close", this};
FButtonGroup m_digModeGroup{"Digital Mode", this};
FRadioButton m_modeDMR{"DMR", &m_digModeGroup};
FRadioButton m_modeP25{"P25", &m_digModeGroup};
// FRadioButton m_modeNXDN{"NXDN", &m_digModeGroup};
FLabel m_dmrSlotLabel{"DMR Slot: ", this};
FSpinBox m_dmrSlot{this};
};
#endif // __TRANSMIT_WND_BASE_H__

@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Digital Voice Modem - FNE System View
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file UninhibitSubscriberWnd.h
* @ingroup fneSysView
*/
#if !defined(__UNINHIBIT_SUBSCRIBER_WND_H__)
#define __UNINHIBIT_SUBSCRIBER_WND_H__
#include "TransmitWndBase.h"
#include <final/final.h>
using namespace finalcut;
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief This class implements the uninhibit subscriber window.
* @ingroup fneSysView
*/
class HOST_SW_API UninhibitSubscriberWnd final : public TransmitWndBase {
public:
/**
* @brief Initializes a new instance of the UninhibitSubscriberWnd class.
* @param channel Channel data.
* @param widget
*/
explicit UninhibitSubscriberWnd(FWidget* widget = nullptr) : TransmitWndBase{widget}
{
/* stub */
}
private:
FLabel m_dialogLabel{"Uninhibit Subscriber", this};
FLabel m_subscriberLabel{"Subscriber ID: ", this};
FSpinBox m_subscriber{this};
/**
* @brief Initializes the window layout.
*/
void initLayout() override
{
FDialog::setText("Uninhibit Subscriber");
FDialog::setSize(FSize{60, 16});
TransmitWndBase::initLayout();
}
/**
* @brief Initializes window controls.
*/
void initControls() override
{
TransmitWndBase::initControls();
// subscriber entry
{
m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2));
m_dialogLabel.setEmphasis();
m_dialogLabel.setAlignment(Align::Center);
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
m_subscriber.setRange(0, 16777211);
m_subscriber.setValue(1);
m_subscriber.setShadow(false);
m_subscriber.addCallback("changed", [&]() {
if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) {
m_txButton.setEnable(true);
}
else {
m_txButton.setEnable(false);
}
redraw();
});
}
m_dialogLabel.redraw();
m_subscriberLabel.redraw();
redraw();
}
/**
* @brief Helper to transmit.
*/
void setTransmit() override
{
switch (m_mode) {
case modem::STATE_DMR:
{
using namespace dmr;
using namespace dmr::defines;
writeDMR_Ext_Func((uint8_t)m_dmrSlot.getValue(), ExtendedFunctions::UNINHIBIT, WUID_STUNI,
(uint32_t)m_subscriber.getValue());
}
break;
case modem::STATE_P25:
{
using namespace p25;
using namespace p25::defines;
writeP25_Ext_Func(ExtendedFunctions::UNINHIBIT, WUID_FNE, (uint32_t)m_subscriber.getValue());
}
break;
default:
break;
}
}
};
#endif // __UNINHIBIT_SUBSCRIBER_WND_H__
Loading…
Cancel
Save

Powered by TurnKey Linux.