run-time config

main
Tom Early 3 years ago
parent 8fa16713d1
commit 708edc90e9

@ -24,6 +24,8 @@
#include "Configure.h" #include "Configure.h"
// ini file keywords // ini file keywords
#define USRPTXGAIN "UsrpTxGain"
#define USRPRXGAIN "UsrpRxGain"
#define DMRGAININ "DmrYsfGainIn" #define DMRGAININ "DmrYsfGainIn"
#define DMRGAINOUT "DmrYsfGainOut" #define DMRGAINOUT "DmrYsfGainOut"
#define DSTARGAININ "DStarGainIn" #define DSTARGAININ "DStarGainIn"
@ -112,6 +114,10 @@ bool CConfigure::ReadData(const std::string &path)
dmr_in = getSigned(key, value); dmr_in = getSigned(key, value);
else if (0 == key.compare(DMRGAINOUT)) else if (0 == key.compare(DMRGAINOUT))
dmr_out = getSigned(key, value); dmr_out = getSigned(key, value);
else if (0 == key.compare(USRPTXGAIN))
usrp_tx = getSigned(key, value);
else if (0 == key.compare(USRPRXGAIN))
usrp_rx = getSigned(key, value);
else else
badParam(key); badParam(key);
break; break;
@ -135,10 +141,12 @@ bool CConfigure::ReadData(const std::string &path)
} }
std::cout << TRANSCODED << " = " << tcmods << std::endl; std::cout << TRANSCODED << " = " << tcmods << std::endl;
std::cout << DSTARGAININ << " = " << int(dstar_in) << std::endl; std::cout << DSTARGAININ << " = " << dstar_in << std::endl;
std::cout << DSTARGAINOUT << " = " << int(dstar_out) << std::endl; std::cout << DSTARGAINOUT << " = " << dstar_out << std::endl;
std::cout << DMRGAININ << " = " << int(dmr_in) << std::endl; std::cout << DMRGAININ << " = " << dmr_in << std::endl;
std::cout << DMRGAINOUT << " = " << int(dmr_out) << std::endl; std::cout << DMRGAINOUT << " = " << dmr_out << std::endl;
std::cout << USRPTXGAIN << " = " << usrp_tx << std::endl;
std::cout << USRPRXGAIN << " = " << usrp_rx << std::endl;
return false; return false;
} }
@ -146,10 +154,15 @@ bool CConfigure::ReadData(const std::string &path)
int CConfigure::getSigned(const std::string &key, const std::string &value) const int CConfigure::getSigned(const std::string &key, const std::string &value) const
{ {
auto i = std::stoi(value.c_str()); auto i = std::stoi(value.c_str());
if ( i < -90 || i > 90 ) if (i < -36)
{ {
std::cout << "WARNING: " << key << " = " << value << " is out of range. Reset to zero!" << std::endl; std::cout << "WARNING: " << key << " = " << value << " is too low. Limit to -36!" << std::endl;
i = 0; i = -36;
}
else if (i > 36)
{
std::cout << "WARNING: " << key << " = " << value << " is too high. Limit to 36!" << std::endl;
i = 36;
} }
return i; return i;
} }
@ -159,14 +172,16 @@ void CConfigure::badParam(const std::string &key) const
std::cout << "WARNING: Unexpected parameter: '" << key << "'" << std::endl; std::cout << "WARNING: Unexpected parameter: '" << key << "'" << std::endl;
} }
int8_t CConfigure::GetGain(EGainType gt) const int CConfigure::GetGain(EGainType gt) const
{ {
switch (gt) switch (gt)
{ {
case EGainType::dmrin: return int8_t(dmr_in); case EGainType::dmrin: return dmr_in;
case EGainType::dmrout: return int8_t(dmr_out); case EGainType::dmrout: return dmr_out;
case EGainType::dstarin: return int8_t(dstar_in); case EGainType::dstarin: return dstar_in;
case EGainType::dstarout: return int8_t(dstar_out); case EGainType::dstarout: return dstar_out;
case EGainType::usrptx: return usrp_tx;
case EGainType::usrprx: return usrp_rx;
default: return 0; default: return 0;
} }
} }

@ -22,7 +22,7 @@
#include <string> #include <string>
#include <regex> #include <regex>
enum class EGainType { dmrin, dmrout, dstarin, dstarout }; enum class EGainType { dmrin, dmrout, dstarin, dstarout, usrptx, usrprx };
#define IS_TRUE(a) ((a)=='t' || (a)=='T' || (a)=='1') #define IS_TRUE(a) ((a)=='t' || (a)=='T' || (a)=='1')
@ -30,13 +30,13 @@ class CConfigure
{ {
public: public:
bool ReadData(const std::string &path); bool ReadData(const std::string &path);
int8_t GetGain(EGainType gt) const; int GetGain(EGainType gt) const;
std::string GetTCMods(void) const { return tcmods; } std::string GetTCMods(void) const { return tcmods; }
private: private:
// CFGDATA data; // CFGDATA data;
std::string tcmods; std::string tcmods;
int dstar_in, dstar_out, dmr_in, dmr_out; int dstar_in, dstar_out, dmr_in, dmr_out, usrp_tx, usrp_rx;
int getSigned(const std::string &key, const std::string &value) const; int getSigned(const std::string &key, const std::string &value) const;
void badParam(const std::string &key) const; void badParam(const std::string &key) const;

@ -33,17 +33,12 @@
extern CConfigure g_Conf; extern CConfigure g_Conf;
//#define AMBE_GAIN 16 //Encoder gain in dB (I use 16 here)
//#define AMBE2_GAIN -24 //Encoder gain in dB (I use -24 here)
#define USRP_RXGAIN -6
#define USRP_TXGAIN 3
int16_t calcGainVal(float db) int16_t calcGainVal(float db)
{ {
float ratio = powf(10.0, (db/20.0)); float ratio = powf(10.0f, (db/20.0f));
if(db < 0){ if(db < 0.0f){
ratio = (1/ratio) * (-1); ratio = (-1.0f/ratio);
} }
return (int16_t)roundf(ratio); return (int16_t)roundf(ratio);
@ -53,8 +48,8 @@ CController::CController() : keep_running(true) {}
bool CController::Start() bool CController::Start()
{ {
usrp_rxgain = calcGainVal(USRP_RXGAIN); usrp_rxgain = calcGainVal(g_Conf.GetGain(EGainType::usrprx));
usrp_txgain = calcGainVal(USRP_TXGAIN); usrp_txgain = calcGainVal(g_Conf.GetGain(EGainType::usrptx));
if (InitVocoders() || reader.Open(REF2TC)) if (InitVocoders() || reader.Open(REF2TC))
{ {
@ -134,7 +129,7 @@ bool CController::InitVocoders()
{ {
// M17 "devices", one for each module // M17 "devices", one for each module
const std::string modules(g_Conf.GetTCMods()); const std::string modules(g_Conf.GetTCMods());
for ( auto c : modules) for (auto c : modules)
{ {
c2_16[c] = std::unique_ptr<CCodec2>(new CCodec2(false)); c2_16[c] = std::unique_ptr<CCodec2>(new CCodec2(false));
c2_32[c] = std::unique_ptr<CCodec2>(new CCodec2(true)); c2_32[c] = std::unique_ptr<CCodec2>(new CCodec2(true));

@ -33,7 +33,6 @@
#include <thread> #include <thread>
#include "DV3000.h" #include "DV3000.h"
#include "configure.h"
#include "Controller.h" #include "Controller.h"
extern CController Controller; extern CController Controller;

@ -33,7 +33,6 @@
#include <thread> #include <thread>
#include "DV3003.h" #include "DV3003.h"
#include "configure.h"
#include "Controller.h" #include "Controller.h"
extern CController Controller; extern CController Controller;

@ -34,8 +34,10 @@
#include <thread> #include <thread>
#include "DVSIDevice.h" #include "DVSIDevice.h"
#include "configure.h"
#include "Controller.h" #include "Controller.h"
#include "Configure.h"
extern CConfigure g_Conf;
extern CController Controller; extern CController Controller;
@ -565,7 +567,7 @@ void CDVDevice::dump(const char *title, const void *pointer, int length) const
void CDVDevice::FeedDevice() void CDVDevice::FeedDevice()
{ {
const std::string modules(TRANSCODED_MODULES); const std::string modules(g_Conf.GetTCMods());
const auto n = modules.size(); const auto n = modules.size();
while (keep_running) while (keep_running)
{ {

@ -20,7 +20,7 @@
#include "Controller.h" #include "Controller.h"
#include "Configure.h" #include "Configure.h"
// the global controller object // the global objects
CConfigure g_Conf; CConfigure g_Conf;
CController g_Cont; CController g_Cont;

@ -4,55 +4,59 @@ tcd is a hybrid digital voice transcoder for ham radio used by the new URF refle
## Introduction ## Introduction
This will build a new kind of hybrid transcoder that uses AMBE DVSI-based hardware for vocoding digital voice streams used in DStar/DMR/YSF *and* David Rowe's open-source Codec2 used in M17. TCd is optimized for performance by using a highly multi-threaded design that incorporates blocking I/O to make it as efficient as possible. This will build a new kind of hybrid transcoder that uses AMBE DVSI-based hardware for vocoding digital voice streams used in DStar/DMR/YSF *and* David Rowe's open-source Codec2 used in M17 as well as the open-source P25 vocoder, IMBE.
This is the only transcoder that will work with the [URF reflector](https://github.com/n7tae/urfd). This is the only transcoder that will work with the [URF reflector](https://github.com/nostar/urfd).
The imbe_vocoder library is required for P25 and can be found here:
https://github.com/nostar/imbe_vocoder
To use md380_vocoder along with a single DV Dongle on an ARM platform (like RPi) change the line 'swambe2 = false' to 'swambe2 = true' in the Makefile. The md380_vocoder library can be found here:
https://github.com/nostar/md380_vocoder
This software is loosely based on LX3JL's **ambed**, but is easily different enough to be considered an entirely original work. Here are some major differences with ambed: This software is loosely based on LX3JL's **ambed**, but is easily different enough to be considered an entirely original work. Here are some major differences with ambed:
- tcd uses both hardware-based and software-based vocoders, providing a bridge between the closed source vocoders used in DStar, DMR and YSF and open-source vocoders used in M17. - tcd uses both hardware-based and software-based vocoders, providing a bridge between the closed source vocoders used in DStar, DMR and YSF and open-source vocoders used in M17 (Codec2) and P25 (IMBE).
- **UNIX Sockets** are used to communicate between the reflector and this transcoder. This greatly simplifies the code and *significantly* improves transcoding performance. - *UNIX Sockets* are used to communicate between the reflector and this transcoder. This greatly simplifies the code and significantly improves transcoding performance.
- AMBE vocoders are dedicated to an assigned reflector channel. This prevents overloading when processing multiple voice streams and provides the best possible performance for the reflector's clients. - Each configured module has a dedicated encoding and decoding instance running on a different thread. This prevents overloading when processing multiple voice streams and provides the best possible performance for the reflector's clients.
## Constraints and Requirements ## Constraints and Requirements
This branch uses only one 300x device for the AMBE+(DStar) codec. The md380_vocoder library is used for the AMBE+2 (DMR/YSF/NXDN) codec. This means that this branch of tcd must run on an ARM platform like a RPi. This branch uses only one 300x device for the AMBE+(DStar) codec.
Currently, this program must be run locally with its paired URF reflector. Remote transcoding is not yet supported. Currently, this program must be run locally with its paired URF reflector. Remote transcoding is not yet supported.
Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Also, by default, tcd is built without gdb support. Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Also, by default, *tcd* is built without gdb support.
The P25 IMBE software vocoder library is available [here](https://github.com/nostar/imbe_vocoder). See its README.md file for instructions for compiling and installating this library.
If you are running tcd on an ARM-base processor, you can opt to use a software-based vocoder library available [here](https://github.com/nostar/md380_vocoder). This library is used for the AMBE+2 (DMR/YSF/NXDN) codec. If you are going to use this library, *tcd* must run on an ARM platform like a RPi.
The DVSI devices need an FTDI driver which is available [here](https://ftdichip.com/drivers/d2xx-drivers). It's important to know that this driver will only work if the normal Linux kernel ftdi_sio and usbserial drivers are removed. This is automatically done by the system service file used for starting *tcd*.
## Download the repository ## Download the repository
In the parent directory of you urfd repository: In the parent directory of you urfd repository:
```bash ```bash
git clone https://github.com/n7tae/tcd.git git clone https://github.com/nostar/tcd.git
cd tcd cd tcd
``` ```
To be perfectly clear, the urfd reflector repository clone and this clone **must be in the same directory**. To be perfectly clear, the urfd reflector repository clone and this clone **must be in the same directory**.
## Configuring and compiling ## Compiling and configuring *tcd*
Copy the three configuration files to the working directory:
Copy the three configuration files: `cp config/* .` ```bash
Use your favorite text editor: cp config/* .
- *tcd.mk* defines some compile time options. Once you've set these options, do `make` ```
- *tcd.ini* defines run-time options. It is especially imporant that the `Transcoded` line for the tcd.ini file is exactly the same as the same line in the urfd.ini file!
- *tcd.service* is the systemd service file. be sure the `ExecStart` line will successfully start tcd!
## Installing and other activities Use your favorite text editor to edit the following files:
- *tcd.mk* defines some compile time options. If you want to use the md380 vocoder, or change the installation directory, specify it here. Once you've set these options, do `make` to compile *tcd*.
- *tcd.ini* defines run-time options. It is especially imporant that the `Transcoded` line for the tcd.ini file is exactly the same as the same line in the urfd.ini file! Suggested values for vocoder gains are provided.
- *tcd.service* is the systemd service file. be sure the `ExecStart` line will successfully start *tcd* by specifying the path to your *tcd* executable and your tcd.ini file.
If the transcoder is local, all other activities will be performed by the ./radmin scripts in your urfd repo. ## Installing *tcd*
## 73 It is easiest to install and uninstall *tcd* using the ./radmin scripts in your urfd repo. If you want to do this manually:
DE N7TAE ```bash
sudo make install
sudo make uninstall
```

@ -3,13 +3,16 @@
# this is a comment # this is a comment
# VERY IMPORTANT: This need to be idential to the same line in the urfd ini file! # VERY IMPORTANT: This need to be idential to the same line in the urfd ini file!
# this will either be a single letter (for DVSI-3000), or # This will either be a single module (for DVSI-3000), or
# three letters (for DVSI-3003) # up to three modules (for DVSI-3003).
Transcoded = A Transcoded = A
# Gain (or attenuation) in dB should be integers in the range of +/-90 # In dB, 6 dB is a factor of 2 in amplitude, 4 in power.
# Something is probably terribly wrong if you need more than +/-20 # Gain values are limited to -36 to +36. Typical values will usually be less.
DStarGainIn = 0 # Below are suggested values that seem to work well with us
DStarGainOut = 0 DStarGainIn = 16
DmrYsfGainIn = 0 DStarGainOut = -16
DmrYsfGainOut = 0 DmrYsfGainIn = -3
DmrYsfGainOut = 0
UsrpTxGain = 12
UsrpRxGain = -6

Loading…
Cancel
Save

Powered by TurnKey Linux.