Merge pull request #1 from LX3JL/master

최신버전
pull/247/head
sojubox 1 year ago committed by GitHub
commit 6f879189c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

6
.gitignore vendored

@ -1,4 +1,4 @@
*.o
xlxd
ambed
ambedtest
src/xlxd
ambed/ambed
ambedtest/ambedtest

@ -1,124 +1,147 @@
# Copyright
© 2016 Luc Engelmann LX1IQ
The XLX Multiprotocol Gateway Reflector Server is part of the software system
for the D-Star Network.
The sources are published under GPL Licenses.
# Usage
The packages which are described in this document are designed to install server
software which is used for the D-Star network infrastructure.
It requires a 24/7 internet connection which can support 20 voice streams or more
to connect repeaters and hotspot dongles!!
- The server requires a fix IP-address !
- The public IP address should have a DNS record which must be published in the
common host files.
If you want to run this software please make sure that you can provide this
service free of charge, like the developer team provides the software and the
network infrastructure free of charge!
# Requirements
The software packages for Linux are tested on Debian7 (Wheezy) 32 and 64bit or newer.
Raspbian will work but is not recommended.
Please use the stable version listed above, we cannot support others.
# Installation
## Debian 7 (Wheezy) 32 and 64bit
###### After a clean installation of debian make sure to run update and upgrade
```
# apt-get update
# apt-get upgrade
```
###### Install Git
```
# apt-get install git git-core
```
###### Install webserver with PHP5 support
```
# apt-get install apache2 php5
```
###### Install g++ compiler
```
# apt-get install build-essential
# apt-get install g++-4.7 (skip this step on Debian 8.x)
```
###### Download and compile the XLX sources
```
# git clone https://github.com/LX3JL/xlxd.git
# cd xlxd/src/
# make clean
# make
# make install
```
###### Copy startup script "xlxd" to /etc/init.d
```
# cp ~/xlxd/scripts/xlxd /etc/init.d/xlxd
```
###### Adapt the default startup parameters to your needs
```
# pico /etc/init.d/xlxd
```
###### Download the dmrid.dat from the XLXAPI server to your xlxd folder
```
# wget -O /xlxd/dmrid.dat http://xlxapi.rlx.lu/api/exportdmr.php
```
###### Check your FTDI driver and install the AMBE service according to the readme in AMBEd
```
```
###### Last step is to declare the service for automatic startup and shutdown
```
# update-rc.d xlxd defaults
```
###### Start or stop the service with
```
# service xlxd start
# service xlxd stop
```
###### Copy dashboard to /var/www
```
# cp -r ~/xlxd/dashboard /var/www/db
```
###### Give the dashboard read access to the server log file
```
# chmod +r /var/log/messages
```
###### Reboot server to see if the auto-start is working
```
# reboot
```
# Firewall settings #
XLX Server requires the following ports to be open and forwarded properly for in- and outgoing network traffic:
- TCP port 80 (http) optional TCP port 443 (https)
- TCP port 8080 (RepNet) optional
- UDP port 10001 (json interface XLX Core)
- UDP port 10002 (XLX interlink)
- TCP port 22 (ssh) optional TCP port 10022
- UDP port 30001 (DExtra protocol)
- UPD port 20001 (DPlus protocol)
- UDP port 30051 (DCS protocol)
- UDP port 8880 (DMR+ DMO mode)
- UDP port 62030 (MMDVM protocol)
- UDP port 10100 (AMBE controller port)
- UDP port 10101 - 10199 (AMBE transcoding port)
© 2016 Luc Engelmann LX1IQ
# Copyright
© 2016 Jean-Luc Deltombe LX3JL and Luc Engelmann LX1IQ
The XLX Multiprotocol Gateway Reflector Server is part of the software system
for the D-Star Network.
The sources are published under GPL Licenses.
# Supported Protocols since XLX v2.5.x
- In D-Star, Icom-G3Terminal, DExtra, DPLus and DCS
- In DMR, DMRPlus (dongle) and DMRMmdvm
- In C4FM, YSF, Wires-X and IMRS
- XLX Interlink protocol
# Usage
The packages which are described in this document are designed to install server
software which is used for the D-Star network infrastructure.
It requires a 24/7 internet connection which can support 20 voice streams or more
to connect repeaters and hotspot dongles!!
- The server requires a fix IP-address !
- The public IP address should have a DNS record which must be published in the
common host files.
If you want to run this software please make sure that you can provide this
service free of charge, like the developer team provides the software and the
network infrastructure free of charge!
# Requirements
The software packages for Linux are tested on Debian7 (Wheezy) 32 and 64bit or newer.
Raspbian will work but is not recommended.
Please use the stable version listed above, we cannot support others.
# Installation
## Debian 7 (Wheezy) 32 and 64bit
###### After a clean installation of debian make sure to run update and upgrade
```
# apt-get update
# apt-get upgrade
```
###### Install Git
```
# apt-get install git git-core
```
###### Install webserver with PHP5 support
```
# apt-get install apache2 php5
```
###### Install g++ compiler
```
# apt-get install build-essential
# apt-get install g++-4.7 (skip this step on Debian 8.x)
```
###### After downloading and before compiling, please have a look at the main.h file
```
# nano /xlxd/src/main.h
For YSF you need to define a default HotSpot frequency !!!
```
###### Download and compile the XLX sources
```
# git clone https://github.com/LX3JL/xlxd.git
# cd xlxd/src/
# make clean
# make
# make install
```
###### Copy startup script "xlxd" to /etc/init.d
```
# cp ~/xlxd/scripts/xlxd /etc/init.d/xlxd
```
###### Adapt the default startup parameters to your needs
```
# pico /etc/init.d/xlxd
```
###### Download the dmrid.dat from the XLXAPI server to your xlxd folder
```
# wget -O /xlxd/dmrid.dat http://xlxapi.rlx.lu/api/exportdmr.php
```
###### Check your FTDI driver and install the AMBE service according to the readme in AMBEd
```
```
###### Last step is to declare the service for automatic startup and shutdown
```
# update-rc.d xlxd defaults
```
###### Start or stop the service with
```
# service xlxd start
# service xlxd stop
```
###### Copy dashboard to /var/www
```
# cp -r ~/xlxd/dashboard /var/www/db
```
###### Give the dashboard read access to the server log file
```
# chmod +r /var/log/messages
```
###### Reboot server to see if the auto-start is working
```
# reboot
```
# Firewall settings #
XLX Server requires the following ports to be open and forwarded properly for in- and outgoing network traffic:
- TCP port 80 (http) optional TCP port 443 (https)
- TCP port 8080 (RepNet) optional
- UDP port 10001 (json interface XLX Core)
- UDP port 10002 (XLX interlink)
- TCP port 22 (ssh) optional TCP port 10022
- UDP port 42000 (YSF protocol)
- UDP port 30001 (DExtra protocol)
- UPD port 20001 (DPlus protocol)
- UDP port 30051 (DCS protocol)
- UDP port 8880 (DMR+ DMO mode)
- UDP port 62030 (MMDVM protocol)
- UDP port 10100 (AMBE controller port)
- UDP port 10101 - 10199 (AMBE transcoding port)
- UDP port 12345 - 12346 (Icom Terminal presence and request port)
- UDP port 40000 (Icom Terminal dv port)
- UDP port 21110 (Yaesu IMRS protocol)
# YSF Master Server
Pay attention, the XLX Server acts as an YSF Master, which provides 26 wires-x rooms.
It has nothing to do with the regular YSFReflector network, hence you dont need to register your XLX at ysfreflector.de !
Nevertheless it is possible.
© 2016 Jean-Luc Deltombe (LX3JL) and Luc Engelmann (LX1IQ)

@ -0,0 +1,94 @@
//
// cagc.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA AGC code borrowed from Liquid DSP
// Only took the parts we need qnd recoeded it to be close the XLX coding style
// https://github.com/jgaeddert/liquid-dsp/blob/master/src/agc/src/agc.c
#include <math.h>
#include "cagc.h"
#include "main.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CAGC::CAGC(float initialLeveldB)
{
// set internal gain appropriately
m_Gain = pow(10.0f, initialLeveldB/20.0f);
//+- 10dB Margin, TODO Move margin to constant
m_GainMax = pow(10.0f, (initialLeveldB + AGC_CLAMPING)/20.0f);
m_GainMin = pow(10.0f, (initialLeveldB - AGC_CLAMPING)/20.0f);
m_EnergyPrime = 1.0f;
// We do not target full scale to avoid stauration
m_targetEnergy = 32767.0f * pow(10.0f, (initialLeveldB - 25.0)/20.0f);//25 dB below saturation as stated in docs
//we also substract our target gain
//this is the time constant of our AGC...
m_Bandwidth = 1e-2f;//TODO : Move to parameter ?
m_Alpha = m_Bandwidth;
}
////////////////////////////////////////////////////////////////////////////////////////
// get
float CAGC::GetGain()
{
return 20.0f*log10(m_Gain);
}
////////////////////////////////////////////////////////////////////////////////////////
// process
inline void CAGC::ProcessSampleBlock(uint8* voice, int length)
{
for(int i = 0; i < length; i += 2)
{
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply AGC
// apply gain to input sample
float output = input * m_Gain;
// compute output signal energy, scaled to 0 to 1
float instantEnergy = abs(output) / m_targetEnergy;
// smooth energy estimate using single-pole low-pass filter
m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy;
// update gain according to output energy
if (m_EnergyPrime > 1e-6f)
m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) );
// clamp gain
if (m_Gain > m_GainMax)
m_Gain = m_GainMax;
else if(m_Gain < m_GainMin)
m_Gain = m_GainMin;
//write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
}

@ -0,0 +1,56 @@
//
// cagc.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA AGC code largely inspired by Liquid DSP
// Only took the parts we need qnd recoeded it to be close the XLX coding style
// https://github.com/jgaeddert/liquid-dsp/blob/master/src/agc/src/agc.c
#ifndef cagc_h
#define cagc_h
#include "csampleblockprocessor.h"
class CAGC : CSampleBlockProcessor
{
public:
//Constructor
CAGC(float initialLeveldB);
//methods
void ProcessSampleBlock(uint8* voice, int length) ;
float GetGain();//gets current gain
private:
float m_Gain; // current gain value
float m_GainMax, m_GainMin; //gain clamping
float m_targetEnergy; // scale value for target energy
// gain control loop filter parameters
float m_Bandwidth; // bandwidth-time constant
float m_Alpha; // feed-back gain
// signal level estimate
float m_EnergyPrime; // filtered output signal energy estimate
};
#endif /* cgc_h */

@ -48,6 +48,9 @@ public:
// destructor
virtual ~CAmbePacket();
// identity
bool IsAmbe(void) const { return true; }
// get
uint8 GetCodec(void) const { return m_uiCodec; }
uint8 *GetAmbe(void) { return m_uiAmbe; }

@ -134,7 +134,7 @@ void CController::Task(void)
// crack packet
if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) )
{
std::cout << "Stream Open from " << Callsign << std::endl;
std::cout << "Stream Open from " << Callsign << " at " << Ip << std::endl;
// try create the stream
Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut);

@ -0,0 +1,75 @@
//
// cfirfilter.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// FIRFilter by Geoffrey Merck F4FXL / KC3FRA
#include "cfirfilter.h"
#include <string.h>
CFIRFilter::CFIRFilter(const float* taps, int tapsLength)
{
m_taps = new float[tapsLength];
m_buffer = new float[tapsLength];
m_tapsLength = tapsLength;
::memcpy(m_taps, taps, tapsLength * sizeof(float));
::memset(m_buffer, 0, tapsLength * sizeof(float));
m_currentBufferPosition = 0;
}
CFIRFilter::~CFIRFilter()
{
delete[] m_taps;
delete[] m_buffer;
}
inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length)
{
for(int i = 0; i < length; i += 2)
{
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
float output = 0.0f;
int iTaps = 0;
// Buffer latest sample into delay line
m_buffer[m_currentBufferPosition] = input;
for(int i = m_currentBufferPosition; i >= 0; i--)
{
output += m_taps[iTaps++] * m_buffer[i];
}
for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--)
{
output += m_taps[iTaps++] * m_buffer[i];
}
m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
//write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
}

@ -0,0 +1,51 @@
//
// cfirfilter.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// FIRFilter by Geoffrey Merck F4FXL / KC3FRA
#ifndef cfirfilter_h
#define cfirfilter_h
#include "csampleblockprocessor.h"
class CFIRFilter : CSampleBlockProcessor
{
public :
//Constructor
CFIRFilter(const float* taps, int tapsLength);
// Destructor
~CFIRFilter();
// Processing
void ProcessSampleBlock(uint8* voice, int length);
private:
float* m_taps;
int m_tapsLength;
float* m_buffer;
int m_currentBufferPosition;
};
#endif //cfirfilter_h

@ -0,0 +1,53 @@
//
// cfixedgain.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA AGC
#include "cfixedgain.h"
#include <math.h>
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CFixedGain::CFixedGain(float gaindB)
{
m_gaindB = gaindB;
m_gainLinear = pow(10.0f, m_gaindB/20.0f);
}
////////////////////////////////////////////////////////////////////////////////////////
// processing
inline void CFixedGain::ProcessSampleBlock(uint8* voice, int length)
{
for(int i = 0; i < length; i += 2)
{
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply gain
float output = input * m_gainLinear;
//write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
}

@ -0,0 +1,45 @@
//
// cfixedgain.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA
#ifndef cfixedgain_h
#define cfixedgain_h
#include "csampleblockprocessor.h"
class CFixedGain : CSampleBlockProcessor
{
public:
//Constructor
CFixedGain(float gaindB);
//processing
void ProcessSampleBlock(uint8* voice, int length);
private:
float m_gaindB; //gain in dB
float m_gainLinear; //linearized gain
};
#endif /* cfixedgain_h */

@ -24,6 +24,10 @@
#include "main.h"
#include <string.h>
#include "cusb3000interface.h"
#include "cusb3003interface.h"
#include "cusb3003hrinterface.h"
#include "cusb3003df2etinterface.h"
#include "cftdidevicedescr.h"
@ -56,3 +60,537 @@ CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr)
::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription));
::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial));
}
////////////////////////////////////////////////////////////////////////////////////////
// interface factory
int CFtdiDeviceDescr::CreateInterface(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{
int iNbChs = 0;
// single channel devices cannot be created alone
// three channels devices
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) || // DVSI's USB-3003
(::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
(::strcmp(descr->GetDescription(), "DVstick-33") == 0) || // DVMEGA USB-3003 device
(::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
{
iNbChs = CreateUsb3003(descr, channels);
}
// six channels devices
else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
{
iNbChs = CreateUsb3006(descr, channels);
}
// twelves channels devices
else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012
{
iNbChs = CreateUsb3012(descr, channels);
}
// done
return iNbChs;
}
int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceDescr *descr2, std::vector<CVocodecChannel *>*channels)
{
int iNbChs = 0;
// create interface objects
if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) )
{
// create 3000-3000 pair
CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1);
CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2);
iNbChs = CreatePair(Usb3000A, Usb3000B, channels);
}
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) )
{
// create 3003-3000 pair
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1);
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2);
iNbChs = CreatePair(Usb3003, Usb3000, channels);
}
else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) )
{
// create 3000-3003 pair
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1);
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2);
iNbChs = CreatePair(Usb3003, Usb3000, channels);
}
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) )
{
// create 3003-3003 pair
CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1);
CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2);
iNbChs = CreatePair(Usb3003A, Usb3003B, channels);
}
// done
return iNbChs;
}
////////////////////////////////////////////////////////////////////////////////////////
// get
const char * CFtdiDeviceDescr::GetChannelDescription(int ch) const
{
static char descr[FTDI_MAX_STRINGLENGTH];
char tag[3] = "_X";
::strcpy(descr, GetDescription());
if ( ::strlen(descr) >= 2 )
{
descr[::strlen(descr)-2] = 0x00;
tag[1] = (char)ch + 'A';
::strcat(descr, tag);
}
return descr;
}
const char * CFtdiDeviceDescr::GetChannelSerialNumber(int ch) const
{
static char serial[FTDI_MAX_STRINGLENGTH];
::strcpy(serial, GetSerialNumber());
if ( ::strlen(serial) >= 1 )
{
serial[::strlen(serial)-1] = (char)ch + 'A';
}
return serial;
}
int CFtdiDeviceDescr::GetNbChannels(void) const
{
int iNbChs = 0;
// single channel devices
if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000
(::strcmp(m_szDescription, "DVstick-30") == 0) || // DVMEGA AMBE3000 device
(::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV
{
iNbChs = 1;
}
// three channels devices
else if ( (::strcmp(m_szDescription, "USB-3003") == 0) || // DVSI's USB-3003
(::strcmp(m_szDescription, "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
(::strcmp(m_szDescription, "DVstick-33") == 0) || // DVMEGA AMBE 3003 device
(::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3
{
iNbChs = 3;
}
// six channels devices
else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
{
iNbChs = 6;
}
// twelves channels devices
else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012
{
iNbChs = 12;
}
// done
return iNbChs;
}
////////////////////////////////////////////////////////////////////////////////////////
// DVSI's USB-3012 factory helper
//
// This device uses 3 AMBE3003 connected on a single FTDI 4 channels
// USB to serial interface. The reset mechanism is based
// on DTR and SetBreak. Baudrate is 921600
//
int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// create the interfaces for the four 3003 chips
CUsb3003HRInterface *Usb3003A =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0));
CUsb3003HRInterface *Usb3003B =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1));
CUsb3003HRInterface *Usb3003C =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(2), descr->GetChannelSerialNumber(2));
CUsb3003HRInterface *Usb3003D =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(3), descr->GetChannelSerialNumber(3));
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) &&
Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch7
Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003C->AddChannel(Channel);
// ch8
Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003C->AddChannel(Channel);
// ch9
Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003D->AddChannel(Channel);
// ch10
Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003D->AddChannel(Channel);
// ch11
Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel);
// ch12
Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel);
//done
nStreams = 12;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3003B;
delete Usb3003C;
delete Usb3003D;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// LX3JL's USB-3006 factory helper
//
// This device uses 2 AMBE3003 connected on a single FTDI 2 channels
// USB to serial interface. The reset mechanism is based
// on DTR and software reset. Baudrate is 921600
//
int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// create the interfaces for the two 3003 chips
CUsb3003Interface *Usb3003A =
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0));
CUsb3003Interface *Usb3003B =
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1));
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
//done
nStreams = 6;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3003B;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// USB-3003 factory helpers
// DVSI
// DF2ET
// ThumbDV
// DVMEGA
//
// These devices uses a AMBE3003 connected on a single FTDI
// USB to serial interface. The reset mechanism is based
// on DTR and SetBreak, or software. Baudrate is 921600
//
int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// create the interfaces for the 3003 chip
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr);
// init the interface
if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003->AddChannel(Channel);
// done
nStreams = 2;
}
}
else
{
// cleanup
delete Usb3003;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// 1 ch + 1 ch pair creation
int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// init the interfaces
if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// done
nStreams = 2;
}
}
else
{
// cleanup
delete Usb3000A;
delete Usb3000B;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// 3 ch + 3 ch pair creation
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface *Usb3003B, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// done
nStreams = 6;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3003B;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// 3 ch + 1 ch pair creation
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
{
int nStreams = 0;
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// done
nStreams = 4;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3000B;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// interface instantiation helpers
CUsb3003Interface *CFtdiDeviceDescr::InstantiateUsb3003(CFtdiDeviceDescr *descr)
{
CUsb3003Interface *Usb3003 = NULL;
// intstantiate the proper version of USB-3003
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003
{
// hardware reset, 921600 bps
Usb3003 = new CUsb3003HRInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
}
else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device
{
// specific hardware reset, 921600 bps
Usb3003 = new CUsb3003DF2ETInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
}
else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
{
// software reset, 921600 bps
Usb3003 = new CUsb3003Interface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
}
else if ( (::strcmp(descr->GetDescription(), "DVstick-33") == 0) ) // DVMEGA AMBE3003 device
{
// specific fardware reset, 921600 bps
Usb3003 = new CUsb3003DF2ETInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
}
// done
return Usb3003;
}
CUsb3000Interface *CFtdiDeviceDescr::InstantiateUsb3000(CFtdiDeviceDescr *descr)
{
CUsb3000Interface *Usb3000 = NULL;
// intstantiate the proper version of USB-3000
if ( (::strcmp(descr->GetDescription(), "USB-3000") == 0) || // DVSI's USB-3000
(::strcmp(descr->GetDescription(), "DVstick-30")== 0) || // DVMEGA AMBE3000 device
(::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV
{
Usb3000 = new CUsb3000Interface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
}
// done
return Usb3000;
}

@ -27,6 +27,7 @@
#include <string.h>
#include "ftd2xx.h"
#include "cvocodecchannel.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
@ -38,6 +39,9 @@
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUsb3000Interface;
class CUsb3003Interface;
class CFtdiDeviceDescr
{
public:
@ -48,20 +52,36 @@ public:
// destructor
virtual ~CFtdiDeviceDescr() {}
// interface factory
static int CreateInterface(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
// get
bool IsUsed(void) const {return m_bUsed; }
bool IsUsb3000(void) const { return (::strcmp(m_szDescription, "USB-3000") == 0); }
bool IsUsb3003(void) const { return (::strcmp(m_szDescription, "USB-3003") == 0); }
bool IsUsb3012(void) const { return (::strcmp(m_szDescription, "USB-3012 A") == 0); }
uint32 GetVid(void) const { return m_uiVid; }
uint32 GetPid(void) const { return m_uiPid; }
const char *GetDescription(void) const { return m_szDescription; }
const char *GetSerialNumber(void) const { return m_szSerial; }
bool IsUsed(void) const { return m_bUsed; }
int GetNbChannels(void) const;
uint32 GetVid(void) const { return m_uiVid; }
uint32 GetPid(void) const { return m_uiPid; }
const char *GetDescription(void) const { return m_szDescription; }
const char *GetSerialNumber(void) const { return m_szSerial; }
const char * GetChannelDescription(int) const;
const char * GetChannelSerialNumber(int) const;
// set
void SetUsed(bool used) { m_bUsed = used; }
protected:
// factory helper
static int CreateUsb3012(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateUsb3006(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateUsb3003(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *);
static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *);
protected:
// status
bool m_bUsed;

@ -40,13 +40,17 @@ public:
// destructor
virtual ~CPacket() {};
// identity
virtual bool IsVoice(void) const { return false; }
virtual bool IsAmbe(void) const { return false; }
// get
int GetChannel(void) const { return m_iCh; }
uint8 GetPid(void) const { return m_uiPid; }
int GetChannel(void) const { return m_iCh; }
uint8 GetPid(void) const { return m_uiPid; }
// set
void SetChannel(int i) { m_iCh = i; }
void SetPid(uint8 ui) { m_uiPid = ui; }
void SetChannel(int i) { m_iCh = i; }
void SetPid(uint8 ui) { m_uiPid = ui; }
protected:
// data

@ -0,0 +1,38 @@
//
// csampleprocessor.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA
#ifndef csamplebloclprocessor_h
#define csamplebloclprocessor_h
#include "main.h"
class CSampleBlockProcessor
{
public:
//processing
virtual void ProcessSampleBlock(uint8* voice, int length) = 0;
};
#endif /* csampleprocessor_h */

@ -0,0 +1,94 @@
//
// cagc.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA AGC
#include "main.h"
#include "csignalprocessor.h"
#if USE_AGC == 1
#include "cagc.h"
#else
#include "cfixedgain.h"
#endif
#if USE_BANDPASSFILTER == 1
#include "cfirfilter.h"
#endif
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CSignalProcessor::CSignalProcessor(float gaindB)
{
#if USE_BANDPASSFILTER
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFIRFilter(FILTER_TAPS, FILTER_TAPS_LENGTH));
#endif
#if USE_AGC == 1
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CAGC(gaindB));
#else
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB));
#endif
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CSignalProcessor::~CSignalProcessor()
{
for(int i = 0; i < m_sampleProcessors.size(); i++)
{
delete m_sampleProcessors[i];
}
}
////////////////////////////////////////////////////////////////////////////////////////
// processing
void CSignalProcessor::Process(uint8* voice, int length)
{
/*float sample;
int j;*/
auto processorsSize = m_sampleProcessors.size();
for(int j = 0; j < processorsSize; j++)
{
m_sampleProcessors[j]->ProcessSampleBlock(voice, length);
}
/*for(int i = 0; i < length; i += 2)
{
//Get the sample
sample = (float)(short)MAKEWORD(voice[i+1], voice[i]);
for(j = 0; j < processorsSize; j++)
{
sample = m_sampleProcessors[j]->ProcessSample(sample);
}
//write processed sample back
voice[i] = HIBYTE((short)sample);
voice[i+1] = LOBYTE((short)sample);
}*/
}

@ -0,0 +1,48 @@
//
// csignalprocessor.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA
#ifndef csignalprocessor_h
#define csignalprocessor_h
#include <vector>
#include "csampleblockprocessor.h"
class CSignalProcessor
{
public:
//Constructor
CSignalProcessor(float gaindB);
//Destructor
~CSignalProcessor();
//Processing
void Process(uint8* voice, int length);
private:
std::vector<CSampleBlockProcessor *> m_sampleProcessors;
};
#endif /* csignalprocessor_h */

@ -71,18 +71,20 @@ CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 ui
CStream::~CStream()
{
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
g_Vocodecs.CloseChannel(m_VocodecChannel);
m_VocodecChannel = NULL;
}
// stop thread first
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
// then close everything
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
m_VocodecChannel->Close();
}
}
@ -124,7 +126,7 @@ bool CStream::Init(uint16 uiPort)
}
else
{
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << g_AmbeServer.GetListenIp() << std::endl;
}
// done
@ -134,13 +136,7 @@ bool CStream::Init(uint16 uiPort)
void CStream::Close(void)
{
// close everything
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
m_VocodecChannel->Close();
}
// stop thread first
m_bStopThread = true;
if ( m_pThread != NULL )
{
@ -148,6 +144,14 @@ void CStream::Close(void)
delete m_pThread;
m_pThread = NULL;
}
// then close everything
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
m_VocodecChannel->Close();
}
// report
std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl;
@ -170,7 +174,7 @@ void CStream::Thread(CStream *This)
void CStream::Task(void)
{
CBuffer Buffer;
static CIp Ip;
CIp Ip;
uint8 uiPid;
uint8 Ambe[AMBE_FRAME_SIZE];
CAmbePacket *packet;
@ -203,7 +207,7 @@ void CStream::Task(void)
queue->pop();
// send it to client
EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe());
m_Socket.Send(Buffer, Ip, m_uiPort);
m_Socket.Send(Buffer, m_Ip, m_uiPort);
// and done
delete packet;
}

@ -254,7 +254,7 @@ bool CUsb3000Interface::ResetDevice(void)
{
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
}
// write soft-reset packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )

@ -0,0 +1,164 @@
//
// cusb3003df2etinterface.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET) on 03/11/2017.
// Copyright © 2017 Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET).
// All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
// Created by Florian Wolters (DF2ET) on 03/11/2017.
// Copyright © 2017 Florian Wolters (DF2ET). All rights reserved.
#include "main.h"
#include "ctimepoint.h"
#include "cambepacket.h"
#include "cusb3003df2etinterface.h"
#include "cvocodecs.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUsb3003DF2ETInterface::CUsb3003DF2ETInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial)
{
}
////////////////////////////////////////////////////////////////////////////////////////
// low level
bool CUsb3003DF2ETInterface::OpenDevice(void)
{
FT_STATUS ftStatus;
int baudrate = 921600;
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted.
ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; }
ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
CTimePoint::TaskSleepFor(50);
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
CTimePoint::TaskSleepFor(50);
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
ftStatus = FT_SetRts (m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; }
// for DF2ET-3003 interface pull DTR low to take AMBE3003 out of reset.
ftStatus = FT_SetDtr( m_FtdiHandle );
CTimePoint::TaskSleepFor(50);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; }
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
// done
return true;
}
bool CUsb3003DF2ETInterface::ResetDevice(void)
{
bool ok = false;
FT_STATUS ftStatus;
int len, i;
char rxpacket[100];
std::cout << "Trying DF2ET-3003 soft reset" << std::endl;
DWORD n, b;
char txpacket[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
char reset_packet[7] = { PKT_HEADER, 0, 3, 0, PKT_RESET, PKT_PARITYBYTE, 3 ^ PKT_RESET ^ PKT_PARITYBYTE };
char *p;
for (i = 0; i < 35; i++)
{
p = &txpacket[0];
n = 10;
do
{
ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
if (FT_OK != ftStatus)
{
return 1;
}
n -= b;
p += b;
} while (n > 0);
}
p = &reset_packet[0];
n = 7;
do
{
ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
if (FT_OK != ftStatus)
{
return 1;
}
n -= b;
p += b;
} while (n > 0);
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( ok )
{
std::cout << "DF2ET-3003 soft reset succeeded" << std::endl;
}
else
{
std::cout << "DF2ET-3003 soft reset failed" << std::endl;
std::cout << "Trying DF2ET-3003 hard reset" << std::endl;
ftStatus = FT_ClrDtr( m_FtdiHandle );
CTimePoint::TaskSleepFor(10);
ftStatus = FT_SetDtr( m_FtdiHandle );
CTimePoint::TaskSleepFor(10);
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( ok )
{
std::cout << "DF2ET-3003 hard reset succeeded" << std::endl;
}
else
{
std::cout << "DF2ET-3003 hard reset failed" << std::endl;
}
}
return ok;
}

@ -0,0 +1,57 @@
//
// cusb3003df2etinterface.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET) on 03/11/2017.
// Copyright © 2017 Jean-Luc Deltombe (LX3JL) and Florian Wolters (DF2ET).
// All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cusb3003df2etinterface_h
#define cusb3003df2etinterface_h
#include "ftd2xx.h"
#include "cbuffer.h"
#include "cusb3003interface.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUsb3003DF2ETInterface : public CUsb3003Interface
{
public:
// constructors
CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *);
// destructor
virtual ~CUsb3003DF2ETInterface() {}
protected:
// low level
bool OpenDevice(void);
bool ResetDevice(void);
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cusb3003df2etinterface_h */

@ -0,0 +1,66 @@
//
// cusb3003hrinterface.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 30/10/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cambepacket.h"
#include "cusb3003hrinterface.h"
#include "cvocodecs.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUsb3003HRInterface::CUsb3003HRInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial)
{
}
////////////////////////////////////////////////////////////////////////////////////////
// low level
bool CUsb3003HRInterface::ResetDevice(void)
{
bool ok = false;
FT_STATUS ftStatus;
int len;
char rxpacket[100];
//if the device is a USB-3003, it supports reset via UART break signal
//printf("reset via uart break...\n");
ftStatus = FT_SetBreakOn( m_FtdiHandle );
CTimePoint::TaskSleepFor(10);
ftStatus = FT_SetBreakOff( m_FtdiHandle );
//CTimePoint::TaskSleepFor(10);
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( !ok )
{
std::cout << "USB-3003 hard reset failed" << std::endl;
}
// done
return ok;
}

@ -0,0 +1,55 @@
//
// cusb3003hrinterface.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 30/10/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cusb3003hrinterface_h
#define cusb3003hrinterface_h
#include "ftd2xx.h"
#include "cbuffer.h"
#include "cusb3003interface.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUsb3003HRInterface : public CUsb3003Interface
{
public:
// constructors
CUsb3003HRInterface(uint32, uint32, const char *, const char *);
// destructor
virtual ~CUsb3003HRInterface() {}
protected:
// low level
bool ResetDevice(void);
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cusb3003hrinterface_h */

@ -209,9 +209,9 @@ bool CUsb3003Interface::OpenDevice(void)
ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; }
ftStatus = FT_OpenEx((PVOID)m_szDeviceName, FT_OPEN_BY_DESCRIPTION, &m_FtdiHandle);
ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
CTimePoint::TaskSleepFor(50);
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
CTimePoint::TaskSleepFor(50);
@ -249,22 +249,46 @@ bool CUsb3003Interface::OpenDevice(void)
bool CUsb3003Interface::ResetDevice(void)
{
bool ok = false;
FT_STATUS ftStatus;
int len;
char rxpacket[100];
char zeropacket[10] =
{
0,0,0,0,0,0,0,0,0,0
};
char txpacket[7] =
{
PKT_HEADER,
0,
3,
0,
PKT_RESET,
PKT_PARITYBYTE,
3 ^ PKT_RESET ^ PKT_PARITYBYTE
};
//if the device is a USB-3003, it supports reset via UART break signal
//printf("reset via uart break...\n");
ftStatus = FT_SetBreakOn( m_FtdiHandle );
CTimePoint::TaskSleepFor(10);
ftStatus = FT_SetBreakOff( m_FtdiHandle );
//CTimePoint::TaskSleepFor(10);
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( !ok )
//the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet.
//first send 350 zeros in case, the chip's receive state is still waiting for characters
//if we send more than needed, the exta characters will just get discarded since they do not match the header byte
//after that we send PKT_RESET to reset the device
//As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it.
for ( int i = 0; i < 35 ; i++ )
{
std::cout << "USB-3003 hard reset failed" << std::endl;
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
}
// write soft-reset packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{
// read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( !ok )
{
std::cout << "USB-3003 soft reset failed" << std::endl;
}
}
// done

@ -70,6 +70,7 @@ protected:
bool OpenDevice(void);
bool ResetDevice(void);
bool ConfigureDevice(void);
int GetDeviceFifoSize(void) const { return 2; }
// data
uint8 m_uiChCodecs[USB3003_NB_CH];

@ -33,18 +33,21 @@
#define QUEUE_CHANNEL 0
#define QUEUE_SPEECH 1
// timeout
#define DEVICE_TIMEOUT 600 // in ms
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
{
m_FtdiHandle = NULL;
m_iDeviceFifoLevel = 0;
m_iActiveQueue = QUEUE_CHANNEL;
m_uiVid = uiVid;
m_uiPid = uiPid;
::strcpy(m_szDeviceName, szDeviceName);
::strcpy(m_szDeviceSerial, szDeviceSerial);
m_iSpeechFifolLevel = 0;
m_iChannelFifolLevel = 0;
}
////////////////////////////////////////////////////////////////////////////////////////
@ -52,6 +55,28 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szD
CUsb3xxxInterface::~CUsb3xxxInterface()
{
// stop thread first
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
// delete m_SpeechQueues
for ( int i = 0; i < m_SpeechQueues.size(); i++ )
{
delete m_SpeechQueues[i];
}
m_SpeechQueues.clear();
// delete m_ChannelQueues
for ( int i = 0; i < m_ChannelQueues.size(); i++ )
{
delete m_ChannelQueues[i];
}
m_ChannelQueues.clear();
}
////////////////////////////////////////////////////////////////////////////////////////
@ -65,7 +90,7 @@ bool CUsb3xxxInterface::Init(void)
std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl;
if ( ok &= OpenDevice() )
{
// reset
// reset
//std::cout << "Reseting " << m_szDeviceName << "device" << std::endl;
if ( ok &= ResetDevice() )
{
@ -82,6 +107,13 @@ bool CUsb3xxxInterface::Init(void)
}
std::cout << std::endl;
// create our queues
for ( int i = 0; i < GetNbChannels(); i++ )
{
m_SpeechQueues.push_back(new CPacketQueue);
m_ChannelQueues.push_back(new CPacketQueue);
}
// base class
if ( ok )
{
@ -118,11 +150,10 @@ void CUsb3xxxInterface::Task(void)
{
if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) )
{
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Sp" << iCh << std::endl; std::cout.flush();
#endif
// update fifo status
m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0);
// update fifo level
// as we get a speech packet, it means that the device
// channel fifo input decreased by 1
m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1);
// push back to relevant channel voice queue
// our incoming channel packet has now been through the decoder
@ -133,20 +164,21 @@ void CUsb3xxxInterface::Task(void)
{
Queue = Channel->GetVoiceQueue();
CVoicePacket *clone = new CVoicePacket(VoicePacket);
clone->ApplyGain(Channel->GetSpeechGain());
Channel->ProcessSignal(*clone);
Queue->push(clone);
Channel->ReleaseVoiceQueue();
}
}
else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) )
{
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Ch" << iCh << std::endl; std::cout.flush();
#endif
// update fifo status
m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0);
// update fifo level
// as we get a channel packet, it means that the device
// speech fifo input decreased by 1
m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1);
// push back to relevant channel outcoming queue
// we are done with this packet transcoding
// it's final step
Channel = GetChannelWithChannelOut(iCh);
if ( Channel != NULL )
{
@ -178,9 +210,12 @@ void CUsb3xxxInterface::Task(void)
// get packet
CVoicePacket *Packet = (CVoicePacket *)Queue->front();
Queue->pop();
// this is second step of transcoding
// we just received from hardware a decoded speech packet
// post it to relevant channel encoder
Packet->SetChannel(Channel->GetChannelOut());
m_SpeechQueue.push(Packet);
int i = Channel->GetChannelOut();
Packet->SetChannel(i);
m_SpeechQueues[i]->push(Packet);
// done
done = false;
}
@ -196,9 +231,12 @@ void CUsb3xxxInterface::Task(void)
// get packet
CAmbePacket *Packet = (CAmbePacket *)Queue->front();
Queue->pop();
// this is first step of transcoding
// a fresh new packet to be transcoded is showing up
// post it to relevant channel decoder
Packet->SetChannel(Channel->GetChannelIn());
m_ChannelQueue.push(Packet);
int i = Channel->GetChannelIn();
Packet->SetChannel(i);
m_ChannelQueues[i]->push(Packet);
// done
done = false;
}
@ -207,57 +245,129 @@ void CUsb3xxxInterface::Task(void)
}
} while (!done);
// process device incoming queues
// process device incoming queues (aka to device)
// interlace speech and channels packets
// and make sure that the fifo is always
// fed.
unsigned long iQueueLevel = m_SpeechQueue.size() + m_ChannelQueue.size();
if ( ((m_iDeviceFifoLevel == 0) && (iQueueLevel >= 2)) || (m_iDeviceFifoLevel == 1) )
// and post to final device queue
do
{
if ( m_iActiveQueue == QUEUE_CHANNEL )
done = true;
// loop on all channels
for ( int i = 0; i < GetNbChannels(); i++ )
{
// post next channel packet
if ( !m_ChannelQueue.empty() )
// speech
if ( !m_SpeechQueues[i]->empty() )
{
// get packet
CAmbePacket *Packet = (CAmbePacket *)m_ChannelQueue.front();
m_ChannelQueue.pop();
//Post it
EncodeChannelPacket(&Buffer, Packet->GetChannel(), Packet);
WriteBuffer(Buffer);
m_iDeviceFifoLevel++;
// and delete it
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
#endif
delete Packet;
}
// and interlace
m_iActiveQueue = QUEUE_SPEECH;
CPacket *Packet = m_SpeechQueues[i]->front();
m_SpeechQueues[i]->pop();
// and push to device queue
m_DeviceQueue.push(Packet);
// next
done = false;
}
// ambe
if ( !m_ChannelQueues[i]->empty() )
{
// get packet
CPacket *Packet = m_ChannelQueues[i]->front();
m_ChannelQueues[i]->pop();
// and push to device queue
m_DeviceQueue.push(Packet);
// done = false;
}
}
else
} while (!done);
// process device queue to feed hardware
// make sure that device fifo is fed all the time
int fifoSize = GetDeviceFifoSize();
do
{
done = true;
// any packet to send ?
if ( m_DeviceQueue.size() > 0 )
{
// post next speech packet
if ( !m_SpeechQueue.empty() )
// yes, get it
CPacket *Packet = m_DeviceQueue.front();
Channel = NULL;
if ( Packet->IsVoice() )
Channel = GetChannelWithChannelOut(Packet->GetChannel());
else if ( Packet->IsAmbe() )
Channel = GetChannelWithChannelIn(Packet->GetChannel());
// if channel no longer open, drop packet, don't waste time with lagged packets
if ( (Channel != NULL) && !Channel->IsOpen() )
{
// get packet
CVoicePacket *Packet = (CVoicePacket *)m_SpeechQueue.front();
m_SpeechQueue.pop();
//Post it
EncodeSpeechPacket(&Buffer, Packet->GetChannel(), Packet);
WriteBuffer(Buffer);
m_iDeviceFifoLevel++;
// and delete it
m_DeviceQueue.pop();
delete Packet;
done = false;
continue;
}
// if device fifo level is zero (device idle)
// wait that at least 3 packets are in incoming
// queue before restarting
if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= (fifoSize+1)) )
{
// if too much time elapsed since last packet was sent to device and fifo level is not zero
// then we failed to get reply(s) from device, reset device fifo level to restart communication
if ( (m_iSpeechFifolLevel > 0) && (m_SpeechFifoLevelTimeout.DurationSinceNow() >= (DEVICE_TIMEOUT/1000.0f)) )
{
std::cout << "Reseting " << m_szDeviceName << ":" << m_szDeviceSerial << " device fifo level due to timeout" << std::endl;
m_iSpeechFifolLevel = 0;
if ( CheckIfDeviceNeedsReOpen() )
m_iChannelFifolLevel = 0;
}
if ( (m_iChannelFifolLevel > 0) && (m_ChannelFifoLevelTimeout.DurationSinceNow() >= (DEVICE_TIMEOUT/1000.0f)) )
{
std::cout << "Reseting " << m_szDeviceName << ":" << m_szDeviceSerial << " device fifo level due to timeout" << std::endl;
m_iChannelFifolLevel = 0;
if ( CheckIfDeviceNeedsReOpen() )
m_iSpeechFifolLevel = 0;
}
if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) )
{
// encode & post
EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet);
WriteBuffer(Buffer);
// remove from queue
m_DeviceQueue.pop();
// and delete it
delete Packet;
// update fifo level
m_iSpeechFifolLevel++;
m_SpeechFifoLevelTimeout.Now();
// next
done = false;
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
#endif
delete Packet;
}
else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) )
{
// encode & post
EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet);
WriteBuffer(Buffer);
// remove from queue
m_DeviceQueue.pop();
// and delete it
delete Packet;
// update fifo level
m_iChannelFifolLevel++;
m_ChannelFifoLevelTimeout.Now();
// next
done = false;
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
#endif
}
}
// and interlace
m_iActiveQueue = QUEUE_CHANNEL;
}
}
} while (!done);
// and wait a bit
CTimePoint::TaskSleepFor(2);
@ -289,10 +399,15 @@ bool CUsb3xxxInterface::ReadDeviceVersion(void)
{
// read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
ok = (len != 0);
ok = (len > 0);
//we succeed in reading a packet, print it out
std::cout << "ReadDeviceVersion : ";
for ( i = 4; i < len+4 ; i++ )
for ( i = 5; (i < len+4) && (rxpacket[i] != 0x00); i++ )
{
std::cout << (char)(rxpacket[i] & 0x00ff);
}
std::cout << " ";
for ( i = i+2; (i < len+4) && (rxpacket[i] != 0x00); i++ )
{
std::cout << (char)(rxpacket[i] & 0x00ff);
}
@ -366,6 +481,46 @@ bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, i
}
bool CUsb3xxxInterface::CheckIfDeviceNeedsReOpen(void)
{
bool ok = false;
int len;
char rxpacket[64];
char txpacket[5] =
{
PKT_HEADER,
0,
1,
PKT_CONTROL,
PKT_PRODID
};
// write packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{
// read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
ok = ((len > 0) && (rxpacket[3] == PKT_CONTROL) && (rxpacket[4] == PKT_PRODID));
}
if ( !ok )
{
std::cout << "Device " << m_szDeviceName << ":" << m_szDeviceSerial << " is unresponsive, trying to re-open it..." << std::endl;
FT_Close(m_FtdiHandle);
CTimePoint::TaskSleepFor(100);
if ( OpenDevice() )
{
if ( ResetDevice() )
{
DisableParity();
ConfigureDevice();
}
}
}
return !ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// io level
@ -403,6 +558,13 @@ int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxle
// first read 4 bytes header
if ( FTDI_read_bytes(ftHandle, pkt, 4) )
{
// ensure we got a valid packet header
if ( (pkt[0] != PKT_HEADER) || ((pkt[3] != PKT_CONTROL) && (pkt[3] != PKT_CHANNEL) && (pkt[3] != PKT_SPEECH)) )
{
std::cout << "FTDI_read_packet invalid packet header" << std::endl;
FT_Purge(ftHandle, FT_PURGE_RX);
return 0;
}
// get payload length
plen = (pkt[1] & 0x00ff);
plen <<= 8;

@ -32,6 +32,7 @@
#include "cambepacket.h"
#include "cvoicepacket.h"
#include "cvocodecinterface.h"
#include "ctimepoint.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
@ -98,12 +99,14 @@ protected:
virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {}
// low level
virtual bool OpenDevice(void) { return false; }
virtual bool ResetDevice(void) { return false; }
virtual bool OpenDevice(void) { return false; }
virtual bool ResetDevice(void) { return false; }
bool ReadDeviceVersion(void);
bool DisableParity(void);
virtual bool ConfigureDevice(void) { return false; }
virtual bool ConfigureDevice(void) { return false; }
bool ConfigureChannel(uint8, const uint8 *, int, int);
bool CheckIfDeviceNeedsReOpen(void);
virtual int GetDeviceFifoSize(void) const { return 1; }
// io level
bool ReadBuffer(CBuffer *);
@ -117,17 +120,20 @@ protected:
protected:
// data
uint32 m_uiVid;
uint32 m_uiPid;
char m_szDeviceName[FTDI_MAX_STRINGLENGTH];
char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH];
FT_HANDLE m_FtdiHandle;
uint32 m_uiVid;
uint32 m_uiPid;
char m_szDeviceName[FTDI_MAX_STRINGLENGTH];
char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH];
FT_HANDLE m_FtdiHandle;
// queue
CPacketQueue m_SpeechQueue;
CPacketQueue m_ChannelQueue;
int m_iDeviceFifoLevel;
int m_iActiveQueue;
std::vector<CPacketQueue*> m_SpeechQueues;
std::vector<CPacketQueue*> m_ChannelQueues;
CPacketQueue m_DeviceQueue;
int m_iSpeechFifolLevel;
int m_iChannelFifolLevel;
CTimePoint m_SpeechFifoLevelTimeout;
CTimePoint m_ChannelFifoLevelTimeout;
};
////////////////////////////////////////////////////////////////////////////////////////

@ -27,7 +27,6 @@
#include "cvocodecchannel.h"
#include "cvocodecinterface.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
@ -39,6 +38,7 @@ CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVoc
m_InterfaceOut = InterfaceOut;
m_iChannelOut = iChOut;
m_iSpeechGain = iSpeechGain;
m_signalProcessor = new CSignalProcessor((float)m_iSpeechGain);
}
////////////////////////////////////////////////////////////////////////////////////////
@ -47,6 +47,7 @@ CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVoc
CVocodecChannel::~CVocodecChannel()
{
PurgeAllQueues();
delete m_signalProcessor;
}
////////////////////////////////////////////////////////////////////////////////////////
@ -61,8 +62,8 @@ bool CVocodecChannel::Open(void)
ok = true;
PurgeAllQueues();
std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl;
m_InterfaceIn->GetName() << ":" << m_InterfaceIn->GetSerial() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << m_InterfaceOut->GetSerial() << ":" << (int)m_iChannelOut << " open" << std::endl;
}
return ok;
}
@ -74,8 +75,8 @@ void CVocodecChannel::Close(void)
m_bOpen = false;
PurgeAllQueues();
std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl;
m_InterfaceIn->GetName() << ":" << m_InterfaceIn->GetSerial() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << m_InterfaceOut->GetSerial() << ":" << (int)m_iChannelOut << " closed" << std::endl;
}
}
@ -92,6 +93,15 @@ uint8 CVocodecChannel::GetCodecOut(void) const
return m_InterfaceOut->GetChannelCodec(m_iChannelOut);
}
////////////////////////////////////////////////////////////////////////////////////////
// processing
void CVocodecChannel::ProcessSignal(CVoicePacket& voicePacket)
{
m_signalProcessor->Process(voicePacket.GetVoice(), voicePacket.GetVoiceSize());
}
////////////////////////////////////////////////////////////////////////////////////////
// queues helpers

@ -27,6 +27,8 @@
#define cvocodecchannel_h
#include "cpacketqueue.h"
#include "csignalprocessor.h"
#include "cvoicepacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
@ -54,6 +56,9 @@ public:
int GetChannelOut(void) const { return m_iChannelOut; }
int GetSpeechGain(void) const { return m_iSpeechGain; }
//Processing
void ProcessSignal(CVoicePacket& voicePacket);
// interfaces
bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); }
bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); }
@ -92,6 +97,8 @@ protected:
// settings
int m_iSpeechGain;
private:
CSignalProcessor* m_signalProcessor;
};
////////////////////////////////////////////////////////////////////////////////////////

@ -46,6 +46,7 @@ public:
// get
virtual const char *GetName(void) const { return ""; }
virtual const char *GetSerial(void) const { return ""; }
// manage channels
virtual int GetNbChannels(void) const { return 0; }

@ -24,8 +24,6 @@
#include "main.h"
#include <string.h>
#include "cusb3000interface.h"
#include "cusb3003interface.h"
#include "cvocodecs.h"
////////////////////////////////////////////////////////////////////////////////////////
@ -89,78 +87,162 @@ bool CVocodecs::Init(void)
DiscoverFtdiDevices();
// and create interfaces for the discovered devices
// first handle all even number of channels devices
std::vector<CVocodecChannel *> Multi3003DevicesChs;
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
// create relevant interface
if ( m_FtdiDeviceDescrs[i]->IsUsb3012() )
CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i];
if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) )
{
iNbCh += InitUsb3012(*m_FtdiDeviceDescrs[i]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
// create the object
iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &Multi3003DevicesChs);
// and flag as used
descr->SetUsed(true);
}
else if ( m_FtdiDeviceDescrs[i]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed() )
}
// next handle all single channel devices.
// they must be handeled in pair, or in pair with another
// even number of channels device.
std::vector<CVocodecChannel *> PairsOf3000DevicesChs;
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL;
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) )
{
// another unsed USB-3003 avaliable for a pair ?
// any other single channel device to pair with ?
bool found = false;
int j = i+1;
while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{
if ( m_FtdiDeviceDescrs[j]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed() )
{
found = true;
}
else
{
j++;
}
descr2 = m_FtdiDeviceDescrs[j];
found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1));
j++;
}
// pair ?
// found one ?
if ( found )
{
// yes!
iNbCh += InitUsb3003Pair(*m_FtdiDeviceDescrs[i], *m_FtdiDeviceDescrs[j]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
m_FtdiDeviceDescrs[j]->SetUsed(true);
// yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &PairsOf3000DevicesChs);
// and flag as used
descr1->SetUsed(true);
descr2->SetUsed(true);
}
else
}
}
// now we should have only remaining the 3 channels device(s)
// and possibly an unique single channel device
std::vector<CVocodecChannel *> Single3003DeviceChannels;
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL;
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) )
{
// any other 3 channel device to pair with ?
bool found = false;
int j = i+1;
while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{
// just single
iNbCh += InitUsb3003(*m_FtdiDeviceDescrs[i]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
descr2 = m_FtdiDeviceDescrs[j];
found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 3));
j++;
}
// found one ?
if ( found )
{
// yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Multi3003DevicesChs);
// and flag as used
descr1->SetUsed(true);
descr2->SetUsed(true);
}
}
else if ( m_FtdiDeviceDescrs[i]->IsUsb3000() && !m_FtdiDeviceDescrs[i]->IsUsed() )
}
// at this point we should have only remaining an unique 3 channels
// and or a unique single channel
std::vector<CVocodecChannel *> Combined3003And3000DeviceChannels;
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL;
// Any 3003 ?
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) )
{
// another unsed USB-3000 avaliable for a pair ?
// any single channel device to pair with ?
bool found = false;
int j = i+1;
int j = 0;
while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{
if ( m_FtdiDeviceDescrs[j]->IsUsb3000() && !m_FtdiDeviceDescrs[i]->IsUsed() )
{
found = true;
}
else
{
j++;
}
descr2 = m_FtdiDeviceDescrs[j];
found = ((descr1 != descr2) && !descr2->IsUsed() && (descr2->GetNbChannels() == 1));
j++;
}
// pair ?
// found one ?
if ( found )
{
// yes!
iNbCh += InitUsb3000Pair(*m_FtdiDeviceDescrs[i], *m_FtdiDeviceDescrs[j]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
m_FtdiDeviceDescrs[j]->SetUsed(true);
// yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Combined3003And3000DeviceChannels);
// and flag as used
descr1->SetUsed(true);
descr2->SetUsed(true);
}
else
{
// no, just create a standalone 3003 interface
iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &Single3003DeviceChannels);
// and flag as used
descr1->SetUsed(true);
}
// otherwise anonther unused USB-3003 for a pair ?
}
}
}
// at this point we should possible only have unique 3003 remaining
// now agregate channels by order of priority
// for proper load sharing
// pairs of 3000 devices first
{
for ( int i = 0; i < PairsOf3000DevicesChs.size(); i++ )
{
m_Channels.push_back(PairsOf3000DevicesChs.at(i));
}
PairsOf3000DevicesChs.clear();
}
// next the left-over single 3003 device
{
for ( int i = 0; i < Single3003DeviceChannels.size(); i++ )
{
m_Channels.push_back(Single3003DeviceChannels.at(i));
}
Single3003DeviceChannels.clear();
}
// finally interlace multi-3003 and pairs of 3003 devices which always
// results to 6 channels per pair of 3003
{
int n = (int)Multi3003DevicesChs.size() / 6;
for ( int i = 0; (i < 6) && (n != 0); i++ )
{
for ( int j = 0; j < n; j++ )
{
m_Channels.push_back(Multi3003DevicesChs.at((j*6) + i));
}
}
Multi3003DevicesChs.clear();
}
// and finaly the hybrid combination of 3003 / 3000
{
for ( int i = 0; i < Combined3003And3000DeviceChannels.size(); i++ )
{
m_Channels.push_back(Combined3003And3000DeviceChannels.at(i));
}
Combined3003And3000DeviceChannels.clear();
}
// done
if ( ok )
{
std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels availables" << std::endl;
std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels available" << std::endl;
}
else
{
@ -207,6 +289,7 @@ bool CVocodecs::DiscoverFtdiDevices(void)
list[i].Description, list[i].SerialNumber);
m_FtdiDeviceDescrs.push_back(descr);
}
std::cout << std::endl;
}
else
{
@ -222,221 +305,6 @@ bool CVocodecs::DiscoverFtdiDevices(void)
return ok;
}
int CVocodecs::InitUsb3012(const CFtdiDeviceDescr &descr)
{
int nStreams = 0;
// create the interfaces for the four 3003 chips
CUsb3003Interface *Usb3003A = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_A", descr.GetSerialNumber());
CUsb3003Interface *Usb3003B = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_B", descr.GetSerialNumber());
CUsb3003Interface *Usb3003C = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_C", descr.GetSerialNumber());
CUsb3003Interface *Usb3003D = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_D", descr.GetSerialNumber());
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) &&
Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch5
Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003C->AddChannel(Channel);
// ch6
Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003C->AddChannel(Channel);
// ch7
Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003D->AddChannel(Channel);
// ch8
Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003D->AddChannel(Channel);
// ch9
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch10
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch11
Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel);
// ch12
Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel);
//done
nStreams = 12;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3003B;
delete Usb3003C;
delete Usb3003D;
}
// done
return nStreams;
}
int CVocodecs::InitUsb3003(const CFtdiDeviceDescr &descr)
{
int nStreams = 0;
// create the interfaces for the 3003 chip
CUsb3003Interface *Usb3003 = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3003", descr.GetSerialNumber());
// init the interface
if ( Usb3003->Init(CODEC_NONE) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003->AddChannel(Channel);
// done
nStreams = 2;
}
}
else
{
// cleanup
delete Usb3003;
}
// done
return nStreams;
}
int CVocodecs::InitUsb3003Pair(const CFtdiDeviceDescr &descr1, const CFtdiDeviceDescr &descr2)
{
int nStreams = 0;
// create the interfaces for the two 3003 chips
CUsb3003Interface *Usb3003A = new CUsb3003Interface(descr1.GetVid(), descr1.GetPid(), "USB-3003", descr1.GetSerialNumber());
CUsb3003Interface *Usb3003B = new CUsb3003Interface(descr2.GetVid(), descr2.GetPid(), "USB-3003", descr2.GetSerialNumber());
// init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
// ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003B->AddChannel(Channel);
// ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel);
// done
nStreams = 6;
}
}
else
{
// cleanup
delete Usb3003A;
delete Usb3003B;
}
// done
return nStreams;
}
int CVocodecs::InitUsb3000Pair(const CFtdiDeviceDescr &descr1, const CFtdiDeviceDescr &descr2)
{
int nStreams = 0;
// create the interfaces for the two 3000 chips
CUsb3000Interface *Usb3000A = new CUsb3000Interface(descr1.GetVid(), descr1.GetPid(), "USB-3000", descr1.GetSerialNumber());
CUsb3000Interface *Usb3000B = new CUsb3000Interface(descr2.GetVid(), descr2.GetPid(), "USB-3000", descr2.GetSerialNumber());
// init the interfaces
if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
{
CVocodecChannel *Channel;
// create all channels
{
// ch1
Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS);
m_Channels.push_back(Channel);
Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// ch2
Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS);
m_Channels.push_back(Channel);
Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel);
// done
nStreams = 2;
}
}
else
{
// cleanup
delete Usb3000A;
delete Usb3000B;
}
// done
return nStreams;
}
////////////////////////////////////////////////////////////////////////////////////////
// manage channels

@ -56,10 +56,10 @@ public:
protected:
// initialisation helpers
bool DiscoverFtdiDevices(void);
int InitUsb3012(const CFtdiDeviceDescr &);
int InitUsb3003(const CFtdiDeviceDescr &);
int InitUsb3003Pair(const CFtdiDeviceDescr &, const CFtdiDeviceDescr &);
int InitUsb3000Pair(const CFtdiDeviceDescr &, const CFtdiDeviceDescr &);
// helpers
bool IsEven(int i) const { return ((i % 2) == 0); }
bool IsOdd(int i) const { return !IsEven(i); }
protected:
// array of interfaces

@ -69,18 +69,3 @@ void CVoicePacket::SetVoice(const uint8 *voice, int size)
::memcpy(m_uiVoice, voice, m_iSize);
}
////////////////////////////////////////////////////////////////////////////////////////
// gain
void CVoicePacket::ApplyGain(int dB)
{
float mult = pow(10, dB/20.0);
for ( int i = 0; i < m_iSize; i += 2 )
{
float smp = (float)(short)MAKEWORD(m_uiVoice[i+1], m_uiVoice[i]);
smp *= mult;
m_uiVoice[i] = HIBYTE((short)smp);
m_uiVoice[i+1] = LOBYTE((short)smp);
}
}

@ -47,7 +47,10 @@ public:
// destructor
virtual ~CVoicePacket();
// identity
bool IsVoice(void) const { return true; }
// get
uint8 *GetVoice(void) { return m_uiVoice; }
int GetVoiceSize(void) const { return m_iSize; }
@ -55,9 +58,6 @@ public:
// set
void SetVoice(const uint8 *, int);
// gain
void ApplyGain(int);
protected:
// data
int m_iSize;

@ -97,7 +97,7 @@ int main(int argc, const char * argv[])
g_AmbeServer.SetListenIp(CIp(argv[1]));
// and let it run
std::cout << "Starting AMBEd" << std::endl << std::endl;
std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
if ( !g_AmbeServer.Start() )
{
std::cout << "Error starting AMBEd" << std::endl;
@ -114,8 +114,12 @@ int main(int argc, const char * argv[])
}
#else
// wait any key
for (;;);
//std::cin.get();
for (;;)
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
//std::cin.get();
}
#endif
// and wait for end

@ -48,8 +48,8 @@
// version -----------------------------------------------------
#define VERSION_MAJOR 1
#define VERSION_MINOR 1
#define VERSION_REVISION 1
#define VERSION_MINOR 3
#define VERSION_REVISION 5
// global ------------------------------------------------------
@ -59,8 +59,6 @@
// Transcoder server --------------------------------------------
#define TRANSCODER_PORT 10100 // UDP port
#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds
#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds
// Codecs -------------------------------------------------------
#define CODEC_NONE 0
@ -68,9 +66,14 @@
#define CODEC_AMBE2PLUS 2
// Transcoding speech gains
#define CODECGAIN_AMBEPLUS -10 // in dB
#define CODECGAIN_AMBEPLUS -10 // in dB
#define CODECGAIN_AMBE2PLUS +10 // in dB
// Transcoding Tweaks
#define USE_AGC 0
#define AGC_CLAMPING 3 //clamps the AGC gain to +- this value
#define USE_BANDPASSFILTER 1
// Timeouts -----------------------------------------------------
#define STREAM_ACTIVITY_TIMEOUT 3 // in seconds
@ -96,6 +99,39 @@ typedef unsigned int uint;
#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF))
#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF))
////////////////////////////////////////////////////////////////////////////////////////
// FIR Filter coefficients computed to be the closest to the recommended filter in
// Documentation
//
// Following GNU Octave script was used
/*
pkg load signal;
fsamp = 8000;
fcuts = [300 400 3000 3400];
mags = [0 1 0];
devs = [0.2 1 0.2];
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fsamp);
n = n + rem(n,2);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
freqz(hh);
[H,f] = freqz(hh,1,1024,fsamp);
plot(f,abs(H))
disp(hh);
grid
*/
#if USE_BANDPASSFILTER == 1
const float FILTER_TAPS[] {
-0.05063341f, -0.00060337f, -0.08892498f, -0.02026701f, -0.05940750f, -0.10977641f, 0.03244024f, -0.22304499f,
0.11452865f, 0.72500000f, 0.11452865f, -0.22304499f, 0.03244024f, -0.10977641f, -0.05940750f, -0.02026701f,
-0.08892498f, -0.00060337f, -0.05063341f };
#define FILTER_TAPS_LENGTH 19
#endif
////////////////////////////////////////////////////////////////////////////////////////
// global objects

@ -14,9 +14,9 @@ $(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $< -o $@
clean:
$(RM) *.o
$(RM) $(EXECUTABLE) *.o
install:
mkdir -p /ambed
cp ./ambed /ambed/
cp $(EXECUTABLE) /ambed/
cp ./run /ambed/

@ -3,7 +3,7 @@
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 09/07/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2017-2019 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
@ -22,26 +22,36 @@
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
VERSION: 1.3.4
Hardware compatibility.
======================
This version of ambed is compatible with DVSI's USB-3000, USB-3003, USB-3012 device
and ThumbDV
This version of ambed is compatible with:
- DF2ET's AMBE3003USB opensource device (https://github.com/phl0/AMBE3003USB)
- LX3JL's USB-3006 opensource device (https://github.com/lx3jl/usb-3006)
- DVSI's USB-3000 device
- DVSI's USB-3003 device
- DVSI's USB-3012 device
- NWDR's ThumbDV device
- NWDR's ThumbDV-3 device
- DVMEGA AMBE3000 device
- DVMEGA AMBE3003 device
Available transcoding channels per device:
device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels
----------------------------------------------------------------------
USB-3000(pair) 1 1 2
USB-3003 1 1 1
USB-3003(pair) 3 3 not tested
USB-3012 6 6 8
Multiple USB-3xxx can be used at the same time.
You need to use USB-3000 by pairs.
ThumbDV is recognized as USB-3000.
ThumbDV must be programed with FT-Prog (Provided by FTDI) by modifying device description as "USB-3000".
-------------------------------------------------------------------------
3000(pair) 1 1 2
3003 1 1 2
3003(pair) 3 3 4
3003-3000(pair) 2 2 4
3006 3 3 6
3012 6 6 12
Multiple devices can be used at the same time.
You need to use 3000 by pairs or paired with a 3003
Do not to use USB hubs as they have proven making
system behaviour unreliable.
Instructions:
=============
@ -61,8 +71,8 @@ Follow FTDI provided documentation for installation and testing of the drivers.
# git clone https://github.com/LX3JL/xlxd.git
# cd xlxd/ambed/
# make
# make clean
# make
# make install
3) configuring ambed startup script

@ -45,6 +45,7 @@ CCodecStream::CCodecStream(uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut)
m_bConnected = false;
m_iAmbeSrcPtr = 0;
m_iAmbeDestPtr = 0;
m_uiNbTotalPacketSent = 0;
m_uiNbPacketSent = 0;
m_uiNbPacketReceived = 0;
m_uiNbPacketBad = 0;
@ -120,6 +121,7 @@ bool CCodecStream::Init(uint16 uiPort)
m_pThread = new std::thread(CCodecStream::Thread, this);
m_bConnected = true;
m_FrameTimer.Now();
m_uiNbTotalPacketSent = 0;
ResetStats();
}
else
@ -181,11 +183,12 @@ void CCodecStream::Task(void)
// and increment pointer
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
m_uiNbTotalPacketSent++;
m_uiNbPacketSent++;
}*/
// any packt to send to trancoder ?
uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbPacketSent;
uint32 uiNbPacketToSend = (uint32)(m_FrameTimer.DurationSinceNow() * 50.0) - m_uiNbTotalPacketSent;
if ( uiNbPacketToSend > 0 )
{
for ( int i = 0; i < uiNbPacketToSend; i++ )
@ -196,6 +199,7 @@ void CCodecStream::Task(void)
// and increment pointer
m_iAmbeSrcPtr = (m_iAmbeSrcPtr + 1) % m_AmbeSrc.size();
m_uiNbTotalPacketSent++;
m_uiNbPacketSent++;
}
}
@ -283,15 +287,19 @@ void CCodecStream::ResetStats(void)
void CCodecStream::DisplayStats(void)
{
//double fps = (double)m_uiNbPacketSent / m_StatsTimer.DurationSinceNow();
double fps = (double)m_uiNbPacketReceived / m_StatsTimer.DurationSinceNow();
// get stats
uint32 uiSent = m_uiNbPacketSent;
uint32 uiReceived = m_uiNbPacketReceived;
uint32 uiBad = m_uiNbPacketBad;
double fps = (double)uiReceived / m_StatsTimer.DurationSinceNow();
std::cout << "Stream " << (int)m_uiStreamId << " (" << (int)m_uiCodecIn << "->" << (int)m_uiCodecOut << ") : ";
std::cout << m_uiNbPacketSent << " / " << m_uiNbPacketReceived << " / " << m_uiNbPacketTimeout;
//std::cout << " / " << m_uiNbPacketBad;
std::cout << " ; " << fps << " fps";
// resets
ResetStats();
std::cout << std::endl;
m_uiNbPacketBad = 0;
// displays
char sz[256];
sprintf(sz, "Stream %d (%d->%d) : %u / %u / %u : %.1f fps",
m_uiStreamId, m_uiCodecIn, m_uiCodecOut,
uiSent, uiReceived, uiBad, fps);
std::cout << sz << std::endl;
}

@ -99,6 +99,7 @@ protected:
std::thread *m_pThread;
CTimePoint m_TimeoutTimer;
CTimePoint m_FrameTimer;
uint32 m_uiNbTotalPacketSent;
// stats
CTimePoint m_StatsTimer;

@ -14,4 +14,4 @@ $(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $< -o $@
clean:
$(RM) *.o
$(RM) $(EXECUTABLE) *.o

@ -0,0 +1,17 @@
#########################################################################################
# XLXD terminal option file
#
# one line per entry
# each entry specifies a terminal option
#
# Valid option:
# address <ip> - Ip address to be used by the terminal route responder
# By default, the request destination address is used.
# If the system is behind a router, set it to the public IP
# If the system runs on the public IP, leave unset.
# modules <modules> - a string with all modules to accept a terminal connection
# Default value is "*", meaning accept all
#
#########################################################################################
#address 193.1.2.3
#modules BCD

@ -1,6 +1,38 @@
xlx db v2.4.1
you can now hide the liveircddb menu button, if you are running your db in https.
- "config.inc.php
- "index.php"
xlx db v2.4.0
- "config.inc.php"
- "index.php"
- "js"
- "layout.css"
xlx db v2.3.9
redesign for the callinghome.php
- "config.inc.php"
- "index.php"
- "functions.php"
xlx db v2.3.8
add support for network traffic statistics via vnstat.
- "config.inc.php"
- "index.php"
- "functions.php"
add traffic.php
xlx db v2.3.7
add background button color change on active page.
add background color change on active page.
- "config.inc.php"
- "layout.css"
@ -66,7 +98,7 @@ xlx db v2.2.2
This version is a major release with voluntary self-registration feature build in.
You need to edit the conf.inc.php to your needs.
On the first run your personal hash to access the database is place in the servers /tmp folder.
On the first run your personal hash to access the database is place in the servers /tmp folder.
Take care to make a backup of this file because this folder is cleaned up after a server reboot.
This version is a major release
@ -94,7 +126,7 @@ xlx db v2.1.4
- "class.reflector.php" improved the flag search
- "country.csv" added serveral prefixes
- "flags" added Puerto Ricco and Åland Islands
- "flags" added Puerto Ricco and Åland Islands
xlx db v2.1.3

@ -10,6 +10,10 @@ h1 {
font-size : 25pt;
}
a img {
border: 0;
}
a.tip {
text-decoration : none;
}
@ -79,6 +83,7 @@ a.tip:hover span {
.menulink {
font-size : 14pt;
text-decoration : none;
white-space : nowrap;
border : 1px #000000 solid;
padding-left : 10px;
padding-top : 3px;
@ -92,6 +97,7 @@ a.tip:hover span {
.menulinkactive {
font-size : 14pt;
text-decoration : none;
white-space : nowrap;
border : 1px #000000 solid;
padding-left : 10px;
padding-top : 3px;
@ -117,18 +123,19 @@ a.tip:hover span {
.listingtable th {
height : 35px;
text-align : center;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0, rgb(201, 231, 233)),
color-stop(0.8, rgb(220, 237, 244))
);
background-image: -o-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -moz-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -webkit-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -ms-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: linear-gradient(to bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-color : #D5EBF0;
background-image : -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0, rgb(201, 231, 233)),
color-stop(0.8, rgb(220, 237, 244))
);
background-image: -o-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -moz-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -webkit-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: -ms-linear-gradient(bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
background-image: linear-gradient(to bottom, rgb(201, 231, 233) 0%, rgb(220, 237, 244) 80%);
}
.listingtable td {
@ -136,7 +143,7 @@ background-image: linear-gradient(to bottom, rgb(201, 231, 233) 0%, rgb(220, 237
}
.listinglink {
font-size : 12pt;
font-size : 12pt;
text-decoration : underline;
color : #60A1DE;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1022 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

@ -2,8 +2,8 @@
session_start();
if (file_exists("./pgs/functions.php")) { require_once("./pgs/functions.php"); } else { die("functions.php does not exist."); }
if (file_exists("./pgs/config.inc.php")) { require_once("./pgs/config.inc.php"); } else { die("config.inc.php does not exist."); }
if (file_exists("./pgs/functions.php")) { require_once("./pgs/functions.php"); } else { die("functions.php does not exist."); }
if (file_exists("./pgs/config.inc.php")) { require_once("./pgs/config.inc.php"); } else { die("config.inc.php does not exist."); }
if (!class_exists('ParseXML')) require_once("./pgs/class.parsexml.php");
if (!class_exists('Node')) require_once("./pgs/class.node.php");
@ -22,34 +22,45 @@ $Reflector->LoadXML();
if ($CallingHome['Active']) {
$CallHomeNow = false;
$LastSync = 0;
$Hash = "";
if (!file_exists($CallingHome['HashFile'])) {
$Hash = CreateCode(16);
$LastSync = 0;
$Ressource = @fopen($CallingHome['HashFile'],"w");
if ($Ressource) {
@fwrite($Ressource, "<?php\n");
@fwrite($Ressource, "\n".'$LastSync = 0;');
@fwrite($Ressource, "\n".'$Hash = "'.$Hash.'";');
@fwrite($Ressource, "\n\n".'?>');
@fclose($Ressource);
@exec("chmod 777 ".$CallingHome['HashFile']);
$CallHomeNow = true;
}
$Ressource = fopen($CallingHome['HashFile'], "w+");
if ($Ressource) {
$Hash = CreateCode(16);
@fwrite($Ressource, "<?php\n");
@fwrite($Ressource, "\n".'$Hash = "'.$Hash.'";');
@fwrite($Ressource, "\n\n".'?>');
@fflush($Ressource);
@fclose($Ressource);
@chmod($HashFile, 0777);
}
}
else {
include($CallingHome['HashFile']);
if ($LastSync < (time() - $CallingHome['PushDelay'])) {
$Ressource = @fopen($CallingHome['HashFile'],"w");
if ($Ressource) {
@fwrite($Ressource, "<?php\n");
@fwrite($Ressource, "\n".'$LastSync = '.time().';');
@fwrite($Ressource, "\n".'$Hash = "'.$Hash.'";');
@fwrite($Ressource, "\n\n".'?>');
@fclose($Ressource);
require_once($CallingHome['HashFile']);
}
if (@file_exists($CallingHome['LastCallHomefile'])) {
if (@is_readable($CallingHome['LastCallHomefile'])) {
$tmp = @file($CallingHome['LastCallHomefile']);
if (isset($tmp[0])) {
$LastSync = $tmp[0];
}
$CallHomeNow = true;
unset($tmp);
}
}
if ($LastSync < (time() - $CallingHome['PushDelay'])) {
$CallHomeNow = true;
$Ressource = @fopen($CallingHome['LastCallHomefile'], "w+");
if ($Ressource) {
@fwrite($Ressource, time());
@fflush($Ressource);
@fclose($Ressource);
@chmod($HashFile, 0777);
}
}
if ($CallHomeNow || isset($_GET['callhome'])) {
$Reflector->SetCallingHome($CallingHome, $Hash);
@ -58,15 +69,14 @@ if ($CallingHome['Active']) {
$Reflector->PrepareReflectorXML();
$Reflector->CallHome();
}
}
else {
$Hash = "";
}
?><!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
@ -84,25 +94,32 @@ else {
if ($PageOptions['PageRefreshActive']) {
echo '
<script src="./js/jquery-1.12.4.min.js"></script>
<script>
var PageRefresh;
function ReloadPage() {
document.location.href = "./index.php';
if (isset($_GET['show'])) {
echo '?show='.$_GET['show'];
}
echo '";
$.get("./index.php'.(isset($_GET['show'])?'?show='.$_GET['show']:'').'", function(data) {
var BodyStart = data.indexOf("<bo"+"dy");
var BodyEnd = data.indexOf("</bo"+"dy>");
if ((BodyStart >= 0) && (BodyEnd > BodyStart)) {
BodyStart = data.indexOf(">", BodyStart)+1;
$("body").html(data.substring(BodyStart, BodyEnd));
}
})
.always(function() {
PageRefresh = setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');
});
}';
if (!isset($_GET['show']) || (($_GET['show'] != 'liveircddb') && ($_GET['show'] != 'reflectors') && ($_GET['show'] != 'interlinks'))) {
echo '
PageRefresh = setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');';
PageRefresh = setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');';
}
echo '
function SuspendPageRefresh() {
clearTimeout(PageRefresh);
clearTimeout(PageRefresh);
}
</script>';
}
@ -113,12 +130,32 @@ else {
<body>
<?php if (file_exists("./tracking.php")) { include_once("tracking.php"); }?>
<div id="top"><img src="./img/header.jpg" alt="XLX Multiprotocol Gateway Reflector" style="margin-top:15px;" />
<br />&nbsp;&nbsp;&nbsp;<?php echo $Reflector->GetReflectorName(); ?>&nbsp;v<?php echo $Reflector->GetVersion(); ?>&nbsp;-&nbsp;Dashboard v<?php echo $PageOptions['DashboardVersion']; ?>&nbsp;&nbsp;/&nbsp;&nbsp;Service uptime: <span id="suptime"><?php echo FormatSeconds($Reflector->GetServiceUptime()); ?></span></div>
<br />&nbsp;&nbsp;&nbsp;<?php echo $Reflector->GetReflectorName(); ?>&nbsp;v<?php echo $Reflector->GetVersion(); ?>&nbsp;-&nbsp;Dashboard v<?php echo $PageOptions['DashboardVersion']; ?>&nbsp;<?php echo $PageOptions['CustomTXT']; ?>&nbsp;&nbsp;/&nbsp;&nbsp;Service uptime: <span id="suptime"><?php echo FormatSeconds($Reflector->GetServiceUptime()); ?></span></div>
<div id="menubar">
<div id="menu">
<table border="0">
<tr>
<td><a href="./index.php" class="menulink<?php if ($_GET['show'] == '') { echo 'active'; } ?>">Users / Modules</a></td><td><a href="./index.php?show=repeaters" class="menulink<?php if ($_GET['show'] == 'repeaters') { echo 'active'; } ?>">Repeaters / Nodes (<?php echo $Reflector->NodeCount(); ?>)</a></td><td><a href="./index.php?show=peers" class="menulink<?php if ($_GET['show'] == 'peers') { echo 'active'; } ?>">Peers (<?php echo $Reflector->PeerCount(); ?>)</a></td><td><a href="./index.php?show=reflectors" class="menulink<?php if ($_GET['show'] == 'reflectors') { echo 'active'; } ?>">Reflectorlist</a></td><td><a href="./index.php?show=liveircddb" class="menulink<?php if ($_GET['show'] == 'liveircddb') { echo 'active'; } ?>">D-Star live</a></td>
<td><a href="./index.php" class="menulink<?php if ($_GET['show'] == '') { echo 'active'; } ?>">Users / Modules</a></td>
<td><a href="./index.php?show=repeaters" class="menulink<?php if ($_GET['show'] == 'repeaters') { echo 'active'; } ?>">Repeaters / Nodes (<?php echo $Reflector->NodeCount(); ?>)</a></td>
<td><a href="./index.php?show=peers" class="menulink<?php if ($_GET['show'] == 'peers') { echo 'active'; } ?>">Peers (<?php echo $Reflector->PeerCount(); ?>)</a></td>
<td><a href="./index.php?show=modules" class="menulink<?php if ($_GET['show'] == 'modules') { echo 'active'; } ?>">Modules list</a></td>
<td><a href="./index.php?show=reflectors" class="menulink<?php if ($_GET['show'] == 'reflectors') { echo 'active'; } ?>">Reflectors list</a></td>
<?php
if ($PageOptions['Traffic']['Show']) {
echo '
<td><a href="./index.php?show=traffic" class="menulink';
if ($_GET['show'] == 'traffic') { echo 'active'; }
echo '">Traffic statistics</a></td>';
}
if ($PageOptions['IRCDDB']['Show']) {
echo '
<td><a href="./index.php?show=liveircddb" class="menulink';
if ($_GET['show'] == 'liveircddb') { echo 'active'; }
echo '">D-Star live</a></td>';
}
?>
</tr>
</table>
</div>
@ -140,7 +177,9 @@ else {
case 'repeaters' : require_once("./pgs/repeaters.php"); break;
case 'liveircddb' : require_once("./pgs/liveircddb.php"); break;
case 'peers' : require_once("./pgs/peers.php"); break;
case 'modules' : require_once("./pgs/modules.php"); break;
case 'reflectors' : require_once("./pgs/reflectors.php"); break;
case 'traffic' : require_once("./pgs/traffic.php"); break;
default : require_once("./pgs/users.php");
}

File diff suppressed because one or more lines are too long

@ -2,30 +2,31 @@
class xReflector {
public $Nodes = null;
public $Stations = null;
public $Peers = null;
private $Flagarray = null;
private $Flagfile = null;
private $CallingHomeActive = null;
private $CallingHomeHash = null;
private $CallingHomeDashboardURL = null;
private $CallingHomeServerURL = null;
private $ReflectorName = null;
private $ServiceUptime = null;
private $ProcessIDFile = null;
private $XMLContent = null;
private $XMLFile = null;
private $ServiceName = null;
private $Version = null;
private $CallingHomeCountry = null;
private $CallingHomeComment = null;
private $CallingHomeOverrideIP = null;
private $Transferinterlink = null;
private $Interlinkfile = null;
public $Nodes = null;
public $Stations = null;
public $Peers = null;
private $Flagarray = null;
private $Flagarray_DXCC = null;
private $Flagfile = null;
private $CallingHomeActive = null;
private $CallingHomeHash = null;
private $CallingHomeDashboardURL = null;
private $CallingHomeServerURL = null;
private $ReflectorName = null;
private $ServiceUptime = null;
private $ProcessIDFile = null;
private $XMLContent = null;
private $XMLFile = null;
private $ServiceName = null;
private $Version = null;
private $CallingHomeCountry = null;
private $CallingHomeComment = null;
private $CallingHomeOverrideIP = null;
private $Transferinterlink = null;
private $Interlinkfile = null;
public $Interlinks = null;
private $InterlinkXML = null;
private $ReflectorXML = null;
private $InterlinkXML = null;
private $ReflectorXML = null;
public function __construct() {
$this->Nodes = array();
@ -40,13 +41,14 @@ class xReflector {
$handle = fopen($this->XMLFile, 'r');
$this->XMLContent = fread($handle, filesize($this->XMLFile));
fclose($handle);
# XLX alphanumeric naming...
$this->ServiceName = substr($this->XMLContent, strpos($this->XMLContent, "<XLX")+4, 3);
if (!is_numeric($this->ServiceName)) {
if (preg_match('/[^a-zA-Z0-9]/', $this->ServiceName) == 1) {
$this->ServiceName = null;
return false;
}
$this->ReflectorName = "XLX".$this->ServiceName;
$LinkedPeersName = "XLX".$this->ServiceName." linked peers";
@ -125,6 +127,7 @@ class xReflector {
public function LoadFlags() {
if ($this->Flagfile != null) {
$this->Flagarray = array();
$this->Flagarray_DXCC = array();
$handle = fopen($this->Flagfile,"r");
if ($handle) {
$i = 0;
@ -134,11 +137,12 @@ class xReflector {
if (isset($tmp[0])) { $this->Flagarray[$i]['Country'] = $tmp[0]; } else { $this->Flagarray[$i]['Country'] = 'Undefined'; }
if (isset($tmp[1])) { $this->Flagarray[$i]['ISO'] = $tmp[1]; } else { $this->Flagarray[$i]['ISO'] = "Undefined"; }
$this->Flagarray[$i]['DXCC'] = array();
//$this->Flagarray[$i]['DXCC'] = array();
if (isset($tmp[2])) {
$tmp2 = explode("-", $tmp[2]);
for ($j=0;$j<count($tmp2);$j++) {
$this->Flagarray[$i]['DXCC'][] = $tmp2[$j];
//$this->Flagarray[$i]['DXCC'][] = $tmp2[$j];
$this->Flagarray_DXCC[ trim($tmp2[$j]) ] = $i;
}
}
$i++;
@ -236,7 +240,12 @@ class xReflector {
$i = 0;
while ($i < $this->NodeCount()) {
if ($this->Nodes[$i]->GetRandomID() == $RandomId) {
return $this->Nodes[$i]->GetCallSign().'-'.$this->Nodes[$i]->GetSuffix();
if (trim($this->Nodes[$i]->GetSuffix()) == "") {
return $this->Nodes[$i]->GetCallSign();
}
else {
return $this->Nodes[$i]->GetCallSign().'-'.$this->Nodes[$i]->GetSuffix();
}
}
$i++;
}
@ -256,25 +265,15 @@ class xReflector {
public function GetFlag($Callsign) {
$Image = "";
$FoundFlag = false;
$Letters = 4;
$Name = "";
while (($Letters >= 2) && (!$FoundFlag)) {
$j = 0;
$Prefix = substr($Callsign, 0, $Letters);
while (($j < count($this->Flagarray)) && (!$FoundFlag)) {
$z = 0;
while (($z < count($this->Flagarray[$j]['DXCC'])) && (!$FoundFlag)) {
if (trim($Prefix) == trim($this->Flagarray[$j]['DXCC'][$z])) {
$Image = $this->Flagarray[$j]['ISO'];
$Name = $this->Flagarray[$j]['Country'];
$FoundFlag = true;
while ($Letters >= 2) {
$Prefix = substr(trim($Callsign), 0, $Letters);
if (isset($this->Flagarray_DXCC[$Prefix])) {
$Image = $this->Flagarray[ $this->Flagarray_DXCC[$Prefix] ]['ISO'];
$Name = $this->Flagarray[ $this->Flagarray_DXCC[$Prefix] ]['Country'];
break;
}
$z++;
}
$j++;
}
$Letters--;
}
return array(strtolower($Image), $Name);

@ -13,54 +13,73 @@ ShowLast3ByteOfIP
$Service = array();
$CallingHome = array();
$PageOptions = array();
$VNStat = array();
$PageOptions['ContactEmail'] = 'your_email'; // Support E-Mail address
$PageOptions['ContactEmail'] = 'your_email'; // Support E-Mail address
$PageOptions['DashboardVersion'] = '2.3.7'; // Dashboard Version
$PageOptions['DashboardVersion'] = '2.4.2'; // Dashboard Version
$PageOptions['PageRefreshActive'] = true; // Activate automatic refresh
$PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds
$PageOptions['PageRefreshActive'] = true; // Activate automatic refresh
$PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds
$PageOptions['NumberOfModules'] = 10; // Number of Modules enabled on reflector
$PageOptions['RepeatersPage'] = array();
$PageOptions['RepeatersPage']['LimitTo'] = 99; // Number of Repeaters to show
$PageOptions['RepeatersPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['RepeatersPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['RepeatersPage']['LimitTo'] = 99; // Number of Repeaters to show
$PageOptions['RepeatersPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['RepeatersPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['PeerPage'] = array();
$PageOptions['PeerPage']['LimitTo'] = 99; // Number of peers to show
$PageOptions['PeerPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['PeerPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['PeerPage']['LimitTo'] = 99; // Number of peers to show
$PageOptions['PeerPage']['IPModus'] = 'ShowFullIP'; // See possible options above
$PageOptions['PeerPage']['MasqueradeCharacter'] = '*'; // Character used for masquerade
$PageOptions['LastHeardPage']['LimitTo'] = 39; // Number of stations to show
$PageOptions['LastHeardPage']['LimitTo'] = 39; // Number of stations to show
$PageOptions['ModuleNames'] = array(); // Module nomination
$PageOptions['ModuleNames'] = array(); // Module nomination
$PageOptions['ModuleNames']['A'] = 'Int.';
$PageOptions['ModuleNames']['B'] = 'Regional';
$PageOptions['ModuleNames']['C'] = 'National';
$PageOptions['ModuleNames']['D'] = '';
$PageOptions['MetaDescription'] = 'XLX is a D-Star Reflector System for Ham Radio Operators.'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaKeywords'] = 'Ham Radio, D-Star, XReflector, XLX, XRF, DCS, REF, '; // Meta Tag Values, usefull forSearch Engine
$PageOptions['MetaAuthor'] = 'LX1IQ'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRevisit'] = 'After 30 Days'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRobots'] = 'index,follow'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaDescription'] = 'XLX is a D-Star Reflector System for Ham Radio Operators.'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaKeywords'] = 'Ham Radio, D-Star, XReflector, XLX, XRF, DCS, REF, '; // Meta Tag Values, usefull forSearch Engine
$PageOptions['MetaAuthor'] = 'LX1IQ'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRevisit'] = 'After 30 Days'; // Meta Tag Values, usefull for Search Engine
$PageOptions['MetaRobots'] = 'index,follow'; // Meta Tag Values, usefull for Search Engine
$PageOptions['UserPage']['ShowFilter'] = true; // Show Filter on Users page
$PageOptions['Traffic']['Show'] = false; // Enable vnstat traffic statistics
$PageOptions['IRCDDB']['Show'] = true; // Show liveircddb, set it to false if you are running your db in https
$PageOptions['UserPage']['ShowFilter'] = true; // Show Filter on Users page
$PageOptions['CustomTXT'] = ''; // custom text in your header
$Service['PIDFile'] = '/var/log/xlxd.pid';
$Service['XMLFile'] = '/var/log/xlxd.xml';
$CallingHome['Active'] = false; // xlx phone home, true or false
$CallingHome['MyDashBoardURL'] = 'http://your_dashboard'; // dashboard url
$CallingHome['ServerURL'] = 'http://xlxapi.rlx.lu/api.php'; // database server, do not change !!!!
$CallingHome['PushDelay'] = 600; // push delay in seconds
$CallingHome['Country'] = "your_country"; // Country
$CallingHome['Comment'] = "your_comment"; // Comment. Max 100 character
$CallingHome['HashFile'] = "/tmp/callinghome.php"; // Make sure the apache user has read and write permissions in this folder.
$CallingHome['OverrideIPAddress'] = ""; // Insert your IP address here. Leave blank for autodetection. No need to enter a fake address.
$CallingHome['InterlinkFile'] = "/xlxd/xlxd.interlink"; // Path to interlink file
$CallingHome['Active'] = false; // xlx phone home, true or false
$CallingHome['MyDashBoardURL'] = 'http://your_dashboard'; // dashboard url
$CallingHome['ServerURL'] = 'http://xlxapi.rlx.lu/api.php'; // database server, do not change !!!!
$CallingHome['PushDelay'] = 600; // push delay in seconds
$CallingHome['Country'] = "your_country"; // Country
$CallingHome['Comment'] = "your_comment"; // Comment. Max 100 character
$CallingHome['HashFile'] = "/tmp/callinghome.php"; // Make sure the apache user has read and write permissions in this folder.
$CallingHome['LastCallHomefile'] = "/tmp/lastcallhome.php"; // lastcallhome.php can remain in the tmp folder
$CallingHome['OverrideIPAddress'] = ""; // Insert your IP address here. Leave blank for autodetection. No need to enter a fake address.
$CallingHome['InterlinkFile'] = "/xlxd/xlxd.interlink"; // Path to interlink file
$VNStat['Interfaces'] = array();
$VNStat['Interfaces'][0]['Name'] = 'eth0';
$VNStat['Interfaces'][0]['Address'] = 'eth0';
$VNStat['Binary'] = '/usr/bin/vnstat';
/*
include an extra config file for people who dont like to mess with shipped config.ing.php
this makes updating dashboard from git a little bit easier
*/
if (file_exists("../config.inc.php")) {
include ("../config.inc.php");
}
?>

@ -10,13 +10,13 @@ Andorra;AD;C3
Angola;AO;D2-D3
Anguilla;AI;VP2E
Annobon Island;GQ;3C0
Antarctica;AQ;CE9-KC4
Antarctica;AQ;CE9-KC4A-KC4U
Antigua and Barbuda;AG;V2
Argentina;AR;LO-LP-LQ-LR-LS-LT-LU-LV-LW
Armenia;AM;EK
Aruba;AW;P4
Ascension Island;SH;ZD8
Asiatic Russia;RU;UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9
Asiatic Russia;RU;UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9-R8-R9
Australia;AU;VK-AX
Austria;AT;OE
Azerbaijan;AZ;4J-4K
@ -57,7 +57,7 @@ Ceuta & Melilla;ES;EA9-EB9-EC9-ED9-EE9-EF9-EG9-EH9
Chad;TD;TT
Chagos Islands;;VQ9
Chatham Islands;NZ;ZL7
Chile;CL;CA-CB-CC-CD-CE
Chile;CL;CA-CB-CC-CD-CE-XQ-XR
China;CN;BA-BB-BC-BD-BE-BF-BG-BH-BI-BJ-BK-BL-BN-BP-BQ-BR-BS-BT-BY-BZ
Christmas Island;CX;VK9X
Cocos Island;;TI9
@ -82,18 +82,18 @@ Djibouti;DJ;J2
Dodecanese;GR;SV5-J45
Dominica;DM;J7
Dominican Republic;DO;HI
East Malaysia;MY;9M6-9M8
East Malaysia;MY;9M6-9M8-9W6-9W8
Easter Island;CL;CE0
Eastern Kiribati (Line Island);KI;T32
Ecuador;EC;HC-HD
Egypt;EG;SU
El Salvador;SV;YS-HU
England;GB;2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MM-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX
England;EN;2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MX-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX
Equatorial Guinea;GQ;3C
Eritrea;ER;E3
Estonia;EE;ES
Ethiopia;ET;ET
European Russia;RU;UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7
European Russia;RU;UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7-R1-R2-R3-R4-R5-R6-R7
Falkland Islands (Malvinas);FK;VP8
Faroe Islands;FO;OY
Fiji;FJ;3D2
@ -117,7 +117,7 @@ Guadeloupe;GP;FG
Guam;GU;KH2
Guantanamo Bay;US;KG4
Guatemala;GT;TG-TD
Guernsey;GG;GU-GP
Guernsey;GG;2U-MU-MP-GU-GP
Guinea;GN;3X
Guinea-Bissau;GW;J5
Guyana;GY;8R
@ -134,13 +134,13 @@ Indonesia;ID;YB-YC-YD-YE-YF-YG-YH
Iran Islamic Republic of;IR;EP-EQ
Iraq;IQ;YI
Ireland;IE;EI-EJ
Isle of Man;IM;GD-GT
Isle of Man;IM;2D-MD-MT-GD-GT
Israel;IL;4X-4Z
Italy;IT;I0-I1-I2-I3-I4-I5-I6-I7-I8-I9-IK-IN-IQ-IR-IS-IT-IU-IV-IW-IZ
Jamaica;JM;6Y
Jan Mayen;NO;JX
Japan;JP;JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N
Jersey;JE;GJ-GH
Japan;JP;JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N-8J-8N
Jersey;JE;2J-MJ-MH-GJ-GH
Johnston Island;US;KH3
Jordan;JO;JY
Kaliningrad;RU;UA2-RA2
@ -148,7 +148,7 @@ Kazakhstan;KZ;UN-UO-UP-UQ
Kenya;KE;5Y-5Z
Kermadec Islands;NZ;ZL8
Korea Democratic People's Republic of;KP;P5
Korea Republic of;KR;HL-6K-6L-6M-6N
Korea Republic of;KR;HL-6K-6L-6M-6N-DS
Kure Island;US;KH7K
Kuwait;KW;9K
Kyrgyzstan;KG;EX
@ -203,7 +203,7 @@ Niger;NE;5U
Nigeria;NG;5N
Niue;NU;ZK2
Norfolk Island;NF;VK9N
Northern Ireland;NIE;GI-GN
Northern Ireland;NIE;2I-MI-MN-GI-GN
Northern Mariana Islands;MP;KH0
Norway;NO;LA-LB-LC-LD-LE-LF-LG-LH-LI-LJ-LK-LL-LM-LN
Oman;OM;A4-YP-YQ-YR
@ -218,7 +218,7 @@ Peru;PE;OA-OB-OC
Philippines;PH;DU-DV-DW-DX-DY-DZ
Pitcairn;PN;VP6
Poland;PL;3Z6-SN-SO-SP-SQ-SR
Portugal;PT;CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU
Portugal;PT;CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT6-CT7-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU
Pratas Islands;;BV9P
Prince Edward & Marion Islands;ZA;ZS8
Puerto Rico;PR;KP3-KP4
@ -242,7 +242,7 @@ Sao Tome and Principe;ST;S9
Sardinia;IT;IS0-IM0
Saudi Arabia;SA;HZ
Scarborough Reef;;BS7
Scotland;SH;GM-GS-2M0
Scotland;SH;2M-MM-MS-GM-GS
Senegal;SN;6V-6W
Serbia;RS;YT-YU
Seychelles;SC;S7
@ -297,9 +297,9 @@ Viet Nam;VN;3W-XV
Virgin Islands British;VG;VP2V
Virgin Islands U.S.;VI;KP2
Wake Island;US;KH9
Wales;WL;2W-GC-GW-MW
Wales;WL;2W-MW-MC-GW-GC
Wallis and Futuna;WF;FW
West Malaysia;MY;9M2-9M4
West Malaysia;MY;9M2-9M4-9W2-9W4
Western Kiribati (Gilbert Island);KI;T30
Western Sahara;EH;S0
Willis Island;AU;VK9W

1 Afghanistan AF YA-T6
10 Angola AO D2-D3
11 Anguilla AI VP2E
12 Annobon Island GQ 3C0
13 Antarctica AQ CE9-KC4 CE9-KC4A-KC4U
14 Antigua and Barbuda AG V2
15 Argentina AR LO-LP-LQ-LR-LS-LT-LU-LV-LW
16 Armenia AM EK
17 Aruba AW P4
18 Ascension Island SH ZD8
19 Asiatic Russia RU UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9 UA0-UA8-UA9-UB0-UB8-UB9-UC0-UC8-UC9-UD0-UD8-UD9-UE0-UE8-UE9-UF0-UF8-UF9-UG0-UG8-UG9-UH0-UH8-UH9-UI0-UI8-UI9-RA0-RA8-RA9-RB0-RB8-RB9-RC0-RC8-RC9-RD0-RD8-RD9-RE0-RE8-RE9-RF0-RF8-RF9-RG0-RG8-RG9-RH0-RH8-RH9-RI0-RI8-RI9-RJ0-RJ8-RJ9-RK0-RK8-RK9-RL0-RL8-RL9-RM0-RM8-RM9-RN0-RN8-RN9-RO0-RO8-RO9-RP0-RP8-RP9-RQ0-RQ8-RQ9-RR0-RR8-RR9-RS0-RS8-RS9-RT0-RT8-RT9-RU0-RU8-RU9-RV0-RV8-RV9-RW0-RW8-RW9-RX0-RX8-RX9-RY0-RY8-RY9-RZ0-RZ8-RZ9-R8-R9
20 Australia AU VK-AX
21 Austria AT OE
22 Azerbaijan AZ 4J-4K
57 Chad TD TT
58 Chagos Islands VQ9
59 Chatham Islands NZ ZL7
60 Chile CL CA-CB-CC-CD-CE CA-CB-CC-CD-CE-XQ-XR
61 China CN BA-BB-BC-BD-BE-BF-BG-BH-BI-BJ-BK-BL-BN-BP-BQ-BR-BS-BT-BY-BZ
62 Christmas Island CX VK9X
63 Cocos Island TI9
82 Dodecanese GR SV5-J45
83 Dominica DM J7
84 Dominican Republic DO HI
85 East Malaysia MY 9M6-9M8 9M6-9M8-9W6-9W8
86 Easter Island CL CE0
87 Eastern Kiribati (Line Island) KI T32
88 Ecuador EC HC-HD
89 Egypt EG SU
90 El Salvador SV YS-HU
91 England GB EN 2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MM-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX 2E-M0-M1-M2-M3-M4-M5-M6-M7-M8-M9-MB-MX-G0-G1-G2-G3-G4-G5-G6-G7-G8-G9-GB-GX
92 Equatorial Guinea GQ 3C
93 Eritrea ER E3
94 Estonia EE ES
95 Ethiopia ET ET
96 European Russia RU UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7 UA1-UA3-UA4-UA5-UA6-UA7-UB1-UB2-UB3-UB4-UB5-UB6-UB7-UC1-UC2-UC3-UC4-UC5-UC6-UC7-UD1-UD2-UD3-UD4-UD5-UD6-UD7-UE1-UE2-UE3-UE4-UE5-UE6-UE7-UF1-UF2-UF3-UF4-UF5-UF6-UF7-UG1-UG2-UG3-UG4-UG5-UG6-UG7-UH1-UH2-UH3-UH4-UH5-UH6-UH7-UI1-UI2-UI3-UI4-UI5-UI6-UI7-RA1-RA3-RA4-RA5-RA6-RA7-RB1-RB2-RB3-RB4-RB5-RB6-RB7-RC1-RC2-RC3-RC4-RC5-RC6-RC7-RD1-RD2-RD3-RD4-RD5-RD6-RD7-RE1-RE2-RE3-RE4-RE5-RE6-RE7-RF1-RF2-RF3-RF4-RF5-RF6-RF7-RG1-RG2-RG3-RG4-RG5-RG6-RG7-RH1-RH2-RH3-RH4-RH5-RH6-RH7-RI1-RI2-RI3-RI4-RI5-RI6-RI7-RJ1-RJ2-RJ3-RJ4-RJ5-RJ6-RJ7-RK1-RK2-RK3-RK4-RK5-RK6-RK7-RL1-RL2-RL3-RL4-RL5-RL6-RL7-RM1-RM2-RM3-RM4-RM5-RM6-RM7-RN1-RN2-RN3-RN4-RN5-RN6-RN7-RO1-RO2-RO3-RO4-RO5-RO6-RO7-RP1-RP2-RP3-RP4-RP5-RP6-RP7-RQ1-RQ2-RQ3-RQ4-RQ5-RQ6-RQ7-RR1-RR2-RR3-RR4-RR5-RR6-RR7-RS1-RS2-RS3-RS4-RS5-RS6-RS7-RT1-RT2-RT3-RT4-RT5-RT6-RT7-RU1-RU2-RU3-RU4-RU5-RU6-RU7-RV1-RV2-RV3-RV4-RV5-RV6-RV7-RW1-RW2-RW3-RW4-RW5-RW6-RW7-RX1-RX2-RX3-RX4-RX5-RX6-RX7-RY1-RY2-RY3-RY4-RY5-RY6-RY7-RZ1-RZ2-RZ3-RZ4-RZ5-RZ6-RZ7-R1-R2-R3-R4-R5-R6-R7
97 Falkland Islands (Malvinas) FK VP8
98 Faroe Islands FO OY
99 Fiji FJ 3D2
117 Guam GU KH2
118 Guantanamo Bay US KG4
119 Guatemala GT TG-TD
120 Guernsey GG GU-GP 2U-MU-MP-GU-GP
121 Guinea GN 3X
122 Guinea-Bissau GW J5
123 Guyana GY 8R
134 Iran Islamic Republic of IR EP-EQ
135 Iraq IQ YI
136 Ireland IE EI-EJ
137 Isle of Man IM GD-GT 2D-MD-MT-GD-GT
138 Israel IL 4X-4Z
139 Italy IT I0-I1-I2-I3-I4-I5-I6-I7-I8-I9-IK-IN-IQ-IR-IS-IT-IU-IV-IW-IZ
140 Jamaica JM 6Y
141 Jan Mayen NO JX
142 Japan JP JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N JA-JB-JC-JD-JE-JF-JG-JH-JI-JJ-JK-JL-JM-JN-JO-JP-JQ-JR-JS-7J-7K-7L-7M-7N-8J-8N
143 Jersey JE GJ-GH 2J-MJ-MH-GJ-GH
144 Johnston Island US KH3
145 Jordan JO JY
146 Kaliningrad RU UA2-RA2
148 Kenya KE 5Y-5Z
149 Kermadec Islands NZ ZL8
150 Korea Democratic People's Republic of KP P5
151 Korea Republic of KR HL-6K-6L-6M-6N HL-6K-6L-6M-6N-DS
152 Kure Island US KH7K
153 Kuwait KW 9K
154 Kyrgyzstan KG EX
203 Nigeria NG 5N
204 Niue NU ZK2
205 Norfolk Island NF VK9N
206 Northern Ireland NIE GI-GN 2I-MI-MN-GI-GN
207 Northern Mariana Islands MP KH0
208 Norway NO LA-LB-LC-LD-LE-LF-LG-LH-LI-LJ-LK-LL-LM-LN
209 Oman OM A4-YP-YQ-YR
218 Philippines PH DU-DV-DW-DX-DY-DZ
219 Pitcairn PN VP6
220 Poland PL 3Z6-SN-SO-SP-SQ-SR
221 Portugal PT CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU CQ0-CQ1-CQ2-CQ3-CQ7-CQ8-CR1-CR2-CR3-CR5-CR6-CR7-CR8-CR9-CS2-CS3-CS4-CS5-CS7-CS8-CT1-CT2-CT3-CT4-CT5-CT6-CT7-CT8-CT9-CU0-CU1-CU2-CU3-CU4-CU5-CU6-CU7-CU8-CU
222 Pratas Islands BV9P
223 Prince Edward & Marion Islands ZA ZS8
224 Puerto Rico PR KP3-KP4
242 Sardinia IT IS0-IM0
243 Saudi Arabia SA HZ
244 Scarborough Reef BS7
245 Scotland SH GM-GS-2M0 2M-MM-MS-GM-GS
246 Senegal SN 6V-6W
247 Serbia RS YT-YU
248 Seychelles SC S7
297 Virgin Islands British VG VP2V
298 Virgin Islands U.S. VI KP2
299 Wake Island US KH9
300 Wales WL 2W-GC-GW-MW 2W-MW-MC-GW-GC
301 Wallis and Futuna WF FW
302 West Malaysia MY 9M2-9M4 9M2-9M4-9W2-9W4
303 Western Kiribati (Gilbert Island) KI T30
304 Western Sahara EH S0
305 Willis Island AU VK9W

@ -52,7 +52,6 @@ function FormatSeconds($seconds) {
function CreateCode ($laenge) {
$zeichen = "1234567890abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNAOPQRSTUVWYXZ";
mt_srand( (double) microtime() * 1000000);
$out = "";
for ($i=1;$i<=$laenge;$i++){
$out .= $zeichen[mt_rand(0,(strlen($zeichen)-1))];
@ -60,4 +59,97 @@ function CreateCode ($laenge) {
return $out;
}
?>
function VNStatLocalize($str) {
global $L;
if (isset($L[$str])) {
return $L[$str];
}
else {
return $str;
}
}
function VNStatGetData($iface, $vnstat_bin) {
$vnstat_data = array();
$fd = @popen("$vnstat_bin --dumpdb -i $iface", "r");
if (is_resource($fd)) {
$buffer = '';
while (!feof($fd)) {
$buffer .= fgets($fd);
}
$vnstat_data = explode("\n", $buffer);
pclose($fd);
}
$day = array();
$hour = array();
$month = array();
$top = array();
if (isset($vnstat_data[0]) && strpos($vnstat_data[0], 'Error') !== false) {
return;
}
foreach($vnstat_data as $line) {
$d = explode(';', trim($line));
if ($d[0] == 'd') {
$day[$d[1]]['time'] = $d[2];
$day[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$day[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$day[$d[1]]['act'] = $d[7];
$day[$d[1]]['rx2'] = $d[5];
$day[$d[1]]['tx2'] = $d[6];
}
else if ($d[0] == 'm') {
$month[$d[1]]['time'] = $d[2];
$month[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$month[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$month[$d[1]]['act'] = $d[7];
$month[$d[1]]['rx2'] = $d[5];
$month[$d[1]]['tx2'] = $d[6];
}
else if ($d[0] == 'h') {
$hour[$d[1]]['time'] = $d[2];
$hour[$d[1]]['rx'] = $d[3];
$hour[$d[1]]['tx'] = $d[4];
$hour[$d[1]]['act'] = 1;
}
else if ($d[0] == 't') {
$top[$d[1]]['time'] = $d[2];
$top[$d[1]]['rx'] = $d[3] * 1024 + $d[5];
$top[$d[1]]['tx'] = $d[4] * 1024 + $d[6];
$top[$d[1]]['act'] = $d[7];
}
else {
$summary[$d[0]] = isset($d[1]) ? $d[1] : '';
}
}
rsort($day);
rsort($month);
rsort($hour);
return array($day, $month, $hour, $day, $month, $top, $summary);
}
function kbytes_to_string($kb) {
$byte_notation = null;
$units = array('TB','GB','MB','KB');
$scale = 1024*1024*1024;
$ui = 0;
$custom_size = isset($byte_notation) && in_array($byte_notation, $units);
while ((($kb < $scale) && ($scale > 1)) || $custom_size) {
$ui++;
$scale = $scale / 1024;
if ($custom_size && $units[$ui] == $byte_notation) {
break;
}
}
return sprintf("%0.2f %s", ($kb/$scale),$units[$ui]);
}
?>

@ -0,0 +1,51 @@
<table class="listingtable">
<tr>
<th width="80" rowspan="2">Module</th>
<th width="130" rowspan="2">Name</th>
<th width="65" rowspan="2">Users</th>
<th colspan="2">DPlus</th>
<th colspan="2">DExtra</th>
<th colspan="2">DCS</th>
<th width="65" rowspan="2">DMR</th>
<th width="65" rowspan="2">YSF<br />DG-ID</th>
</tr>
<tr>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
<th width="100">URCALL</th>
<th width="100">DTMF</th>
</tr>
<?php
$ReflectorNumber = substr($Reflector->GetReflectorName(), 3, 3);
$NumberOfModules = isset($PageOptions['NumberOfModules']) ? min(max($PageOptions['NumberOfModules'],0),26) : 26;
$odd = "";
for ($i = 1; $i <= $NumberOfModules; $i++) {
$module = chr(ord('A')+($i-1));
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'. $module .'</td>
<td align="center">'. (empty($PageOptions['ModuleNames'][$module]) ? '-' : $PageOptions['ModuleNames'][$module]) .'</td>
<td align="center">'. count($Reflector->GetNodesInModulesByID($module)) .'</td>
<td align="center">'. 'REF' . $ReflectorNumber . $module . 'L' .'</td>
<td align="center">'. (is_numeric($ReflectorNumber) ? '*' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. 'XRF' . $ReflectorNumber . $module . 'L' .'</td>
<td align="center">'. (is_numeric($ReflectorNumber) ? 'B' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. 'DCS' . $ReflectorNumber . $module . 'L' .'</td>
<td align="center">'. (is_numeric($ReflectorNumber) ? 'D' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .'</td>
<td align="center">'. (4000+$i) .'</td>
<td align="center">'. (9+$i) .'</td>
</tr>';
}
?>
</table>

@ -43,7 +43,7 @@ for ($i=0;$i<count($Reflectors);$i++) {
<td align="center">'.($i+1).'</td>
<td><a href="'.$DASHBOARDURL.'" target="_blank" class="listinglink" title="Visit the Dashboard of&nbsp;'.$NAME.'">'.$NAME.'</a></td>
<td>'.$COUNTRY.'</td>
<td align="center" valign="middle"><img src="./img/'; if ($LASTCONTACT<(time()-600)) { echo 'down'; } ELSE { echo 'up'; } echo '.png" height="25" /></td>
<td align="center" valign="middle"><img src="./img/'; if ($LASTCONTACT<(time()-1800)) { echo 'down'; } ELSE { echo 'up'; } echo '.png" height="25" /></td>
<td>'.$COMMENT.'</td>
</tr>';
}

@ -1,4 +1,110 @@
<table class="listingtable">
<?php
if (!isset($_SESSION['FilterCallSign'])) {
$_SESSION['FilterCallSign'] = null;
}
if (!isset($_SESSION['FilterProtocol'])) {
$_SESSION['FilterProtocol'] = null;
}
if (!isset($_SESSION['FilterModule'])) {
$_SESSION['FilterModule'] = null;
}
if (isset($_POST['do'])) {
if ($_POST['do'] == 'SetFilter') {
if (isset($_POST['txtSetCallsignFilter'])) {
$_POST['txtSetCallsignFilter'] = trim($_POST['txtSetCallsignFilter']);
if ($_POST['txtSetCallsignFilter'] == "") {
$_SESSION['FilterCallSign'] = null;
}
else {
$_SESSION['FilterCallSign'] = $_POST['txtSetCallsignFilter'];
if (strpos($_SESSION['FilterCallSign'], "*") === false) {
$_SESSION['FilterCallSign'] = "*".$_SESSION['FilterCallSign']."*";
}
}
}
if (isset($_POST['txtSetProtocolFilter'])) {
$_POST['txtSetProtocolFilter'] = trim($_POST['txtSetProtocolFilter']);
if ($_POST['txtSetProtocolFilter'] == "") {
$_SESSION['FilterProtocol'] = null;
}
else {
$_SESSION['FilterProtocol'] = $_POST['txtSetProtocolFilter'];
}
}
if (isset($_POST['txtSetModuleFilter'])) {
$_POST['txtSetModuleFilter'] = trim($_POST['txtSetModuleFilter']);
if ($_POST['txtSetModuleFilter'] == "") {
$_SESSION['FilterModule'] = null;
}
else {
$_SESSION['FilterModule'] = $_POST['txtSetModuleFilter'];
}
}
}
}
if (isset($_GET['do'])) {
if ($_GET['do'] == "resetfilter") {
$_SESSION['FilterModule'] = null;
$_SESSION['FilterProtocol'] = null;
$_SESSION['FilterCallSign'] = null;
}
}
?>
<table class="listingtable"><?php
if ($PageOptions['UserPage']['ShowFilter']) {
echo '
<tr>
<th colspan="9">
<table width="100%" border="0">
<tr>
<td align="left">
<form name="frmFilterCallSign" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.$_SESSION['FilterCallSign'].'" name="txtSetCallsignFilter" placeholder="Callsign" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>';
if (($_SESSION['FilterModule'] != null) || ($_SESSION['FilterCallSign'] != null) || ($_SESSION['FilterProtocol'] != null)) {
echo '
<td><a href="./index.php?show=repeaters&do=resetfilter" class="smalllink">Disable filters</a></td>';
}
echo '
<td align="right" style="padding-right:3px;">
<form name="frmFilterProtocol" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.$_SESSION['FilterProtocol'].'" name="txtSetProtocolFilter" placeholder="Protocol" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>
<td align="right" style="padding-right:3px;">
<form name="frmFilterModule" method="post" action="./index.php?show=repeaters">
<input type="hidden" name="do" value="SetFilter" />
<input type="text" class="FilterField" value="'.$_SESSION['FilterModule'].'" name="txtSetModuleFilter" placeholder="Module" onfocus="SuspendPageRefresh();" onblur="setTimeout(ReloadPage, '.$PageOptions['PageRefreshDelay'].');" />
<input type="submit" value="Apply" class="FilterSubmit" />
</form>
</td>
</table>
</th>
</tr>';
}
?>
<tr>
<th width="25">#</th>
<th width="60">Flag</th>
@ -22,61 +128,86 @@ $odd = "";
$Reflector->LoadFlags();
for ($i=0;$i<$Reflector->NodeCount();$i++) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'.($i+1).'</td>
<td align="center">';
list ($Flag, $Name) = $Reflector->GetFlag($Reflector->Nodes[$i]->GetCallSign());
if (file_exists("./img/flags/".$Flag.".png")) {
echo '<a href="#" class="tip"><img src="./img/flags/'.$Flag.'.png" height="15" alt="'.$Name.'" /><span>'.$Name.'</span></a>';
}
echo '</td>
<td><a href="http://www.aprs.fi/'.$Reflector->Nodes[$i]->GetCallSign();
if ($Reflector->Nodes[$i]->GetSuffix() != "") echo '-'.$Reflector->Nodes[$i]->GetSuffix();
echo '" class="pl" target="_blank">'.$Reflector->Nodes[$i]->GetCallSign();
if ($Reflector->Nodes[$i]->GetSuffix() != "") { echo '-'.$Reflector->Nodes[$i]->GetSuffix(); }
echo '</a></td>
<td>';
if (($Reflector->Nodes[$i]->GetPrefix() == 'REF') || ($Reflector->Nodes[$i]->GetPrefix() == 'XRF')) {
switch ($Reflector->Nodes[$i]->GetPrefix()) {
case 'REF' : echo 'REF-Link'; break;
case 'XRF' : echo 'XRF-Link'; break;
$ShowThisStation = true;
if ($PageOptions['UserPage']['ShowFilter']) {
$CS = true;
if ($_SESSION['FilterCallSign'] != null) {
if (!fnmatch($_SESSION['FilterCallSign'], $Reflector->Nodes[$i]->GetCallSign(), FNM_CASEFOLD)) {
$CS = false;
}
}
}
else {
switch ($Reflector->Nodes[$i]->GetSuffix()) {
case 'A' : echo '23cm'; break;
case 'B' : echo '70cm'; break;
case 'C' : echo '2m'; break;
case 'D' : echo 'Dongle'; break;
case 'G' : echo 'Internet-Gateway'; break;
default : echo '';
$MO = true;
if ($_SESSION['FilterModule'] != null) {
if (trim(strtolower($_SESSION['FilterModule'])) != strtolower($Reflector->Nodes[$i]->GetLinkedModule())) {
$MO = false;
}
}
$PR = true;
if ($_SESSION['FilterProtocol'] != null) {
if (trim(strtolower($_SESSION['FilterProtocol'])) != strtolower($Reflector->Nodes[$i]->GetProtocol())) {
$PR = false;
}
}
$ShowThisStation = ($CS && $MO && $PR);
}
echo '</td>
<td>'.date("d.m.Y H:i", $Reflector->Nodes[$i]->GetLastHeardTime()).'</td>
<td>'.FormatSeconds(time()-$Reflector->Nodes[$i]->GetConnectTime()).' s</td>
<td>'.$Reflector->Nodes[$i]->GetProtocol().'</td>
<td align="center">'.$Reflector->Nodes[$i]->GetLinkedModule().'</td>';
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
if ($ShowThisStation) {
if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; }
echo '
<td>';
$Bytes = explode(".", $Reflector->Nodes[$i]->GetIP());
if ($Bytes !== false && count($Bytes) == 4) {
switch ($PageOptions['RepeatersPage']['IPModus']) {
case 'ShowLast1ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
case 'ShowLast2ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
case 'ShowLast3ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
default : echo $Reflector->Nodes[$i]->GetIP();
<tr height="30" bgcolor="'.$odd.'" onMouseOver="this.bgColor=\'#FFFFCA\';" onMouseOut="this.bgColor=\''.$odd.'\';">
<td align="center">'.($i+1).'</td>
<td align="center">';
list ($Flag, $Name) = $Reflector->GetFlag($Reflector->Nodes[$i]->GetCallSign());
if (file_exists("./img/flags/".$Flag.".png")) {
echo '<a href="#" class="tip"><img src="./img/flags/'.$Flag.'.png" height="15" alt="'.$Name.'" /><span>'.$Name.'</span></a>';
}
echo '</td>
<td><a href="http://www.aprs.fi/'.$Reflector->Nodes[$i]->GetCallSign();
if ($Reflector->Nodes[$i]->GetSuffix() != "") echo '-'.$Reflector->Nodes[$i]->GetSuffix();
echo '" class="pl" target="_blank">'.$Reflector->Nodes[$i]->GetCallSign();
if ($Reflector->Nodes[$i]->GetSuffix() != "") { echo '-'.$Reflector->Nodes[$i]->GetSuffix(); }
echo '</a></td>
<td>';
if (($Reflector->Nodes[$i]->GetPrefix() == 'REF') || ($Reflector->Nodes[$i]->GetPrefix() == 'XRF')) {
switch ($Reflector->Nodes[$i]->GetPrefix()) {
case 'REF' : echo 'REF-Link'; break;
case 'XRF' : echo 'XRF-Link'; break;
}
}
echo '</td>';
else {
switch ($Reflector->Nodes[$i]->GetSuffix()) {
case 'A' : echo '23cm'; break;
case 'B' : echo '70cm'; break;
case 'C' : echo '2m'; break;
case 'D' : echo 'Dongle'; break;
case 'G' : echo 'Internet-Gateway'; break;
default : echo '';
}
}
echo '</td>
<td>'.date("d.m.Y H:i", $Reflector->Nodes[$i]->GetLastHeardTime()).'</td>
<td>'.FormatSeconds(time()-$Reflector->Nodes[$i]->GetConnectTime()).' s</td>
<td>'.$Reflector->Nodes[$i]->GetProtocol().'</td>
<td align="center">'.$Reflector->Nodes[$i]->GetLinkedModule().'</td>';
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
echo '
<td>';
$Bytes = explode(".", $Reflector->Nodes[$i]->GetIP());
if ($Bytes !== false && count($Bytes) == 4) {
switch ($PageOptions['RepeatersPage']['IPModus']) {
case 'ShowLast1ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
case 'ShowLast2ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
case 'ShowLast3ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
default : echo $Reflector->Nodes[$i]->GetIP();
}
}
echo '</td>';
}
echo '
</tr>';
}
echo '
</tr>';
if ($i == $PageOptions['RepeatersPage']['LimitTo']) { $i = $Reflector->NodeCount()+1; }
}

@ -0,0 +1,102 @@
<?php
if (!isset($_GET['iface'])) {
if (isset($VNStat['Interfaces'][0]['Address'])) {
$_GET['iface'] = $VNStat['Interfaces'][0]['Address'];
}
else {
$_GET['iface'] = "";
}
}
else {
$f = false;
$i = 0;
while ($i < count($VNStat['Interfaces']) && (!$f)) {
if ($_GET['iface'] == $VNStat['Interfaces'][$i]['Address']) {
$f = true;
}
$i++;
}
if (!$f) {
$_GET['iface'] = "";
}
}
?>
<table class="listingtable">
<tr>
<th>Network interfaces</th>
<th>Statistics</th>
</tr>
<tr>
<td bgcolor="#F1FAFA" align="left" valign="top" style="padding-left:5px;"><?php
for ($i=0;$i<count($VNStat['Interfaces']);$i++) {
echo '<a href="./index.php?show=traffic&iface='.$VNStat['Interfaces'][$i]['Address'].'" class="listinglink">'.$VNStat['Interfaces'][$i]['Name'].'</a>';
if ($i < count($VNStat['Interfaces'])) {
echo '<br />';
}
}
?></td>
<td bgcolor="#FFFFFF"><?php
$Data = VNStatGetData($_GET['iface'], $VNStat['Binary']);
echo '
<table style="margin:10px;">
<tr>
<td>Day</td>
<td>RX</td>
<td>TX</td>
<td>Avg Rx</td>
<td>Avg TX</td>
</tr>';
for ($i=0;$i<count($Data[0]);$i++) {
if ($Data[0][$i]['time'] > 0) {
echo '
<tr>
<td width="100">'.date("d.m.Y", $Data[0][$i]['time']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['rx']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['tx']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['rx2']).'</td>
<td width="100">'.kbytes_to_string($Data[0][$i]['tx2']).'</td>
</tr>';
}
}
echo '</table>';
echo '
<table style="margin:10px;">
<tr>
<td>Month</td>
<td>RX</td>
<td>TX</td>
<td>Avg Rx</td>
<td>Avg TX</td>
</tr>';
for ($i=0;$i<count($Data[1]);$i++) {
if ($Data[1][$i]['time'] > 0) {
echo '
<tr>
<td width="100">'.date("F", $Data[1][$i]['time']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['rx']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['tx']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['rx2']).'</td>
<td width="100">'.kbytes_to_string($Data[1][$i]['tx2']).'</td>
</tr>';
}
}
echo '</table>';
?>
</td>
</tr>
</table>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save

Powered by TurnKey Linux.