diff --git a/.gitignore b/.gitignore index d5b9992..dffdf1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.o -xlxd -ambed -ambedtest +src/xlxd +ambed/ambed +ambedtest/ambedtest diff --git a/README.md b/README.md index a82d2f1..e50f751 100644 --- a/README.md +++ b/README.md @@ -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 don’t need to register your XLX at ysfreflector.de ! +Nevertheless it is possible. + +© 2016 Jean-Luc Deltombe (LX3JL) and Luc Engelmann (LX1IQ) diff --git a/ambed/cagc.cpp b/ambed/cagc.cpp new file mode 100644 index 0000000..880323d --- /dev/null +++ b/ambed/cagc.cpp @@ -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 . +// ---------------------------------------------------------------------------- +// 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 +#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); + } +} diff --git a/ambed/cagc.h b/ambed/cagc.h new file mode 100644 index 0000000..f0ebf75 --- /dev/null +++ b/ambed/cagc.h @@ -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 . +// ---------------------------------------------------------------------------- +// 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 */ \ No newline at end of file diff --git a/ambed/cambepacket.h b/ambed/cambepacket.h index 13cd124..f6ae00a 100644 --- a/ambed/cambepacket.h +++ b/ambed/cambepacket.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; } diff --git a/ambed/ccontroller.cpp b/ambed/ccontroller.cpp index d6039e8..597d18c 100644 --- a/ambed/ccontroller.cpp +++ b/ambed/ccontroller.cpp @@ -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); diff --git a/ambed/cfirfilter.cpp b/ambed/cfirfilter.cpp new file mode 100644 index 0000000..67a0fb1 --- /dev/null +++ b/ambed/cfirfilter.cpp @@ -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 . +// ---------------------------------------------------------------------------- +// FIRFilter by Geoffrey Merck F4FXL / KC3FRA + +#include "cfirfilter.h" +#include + +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); + } +} + + diff --git a/ambed/cfirfilter.h b/ambed/cfirfilter.h new file mode 100644 index 0000000..85026fb --- /dev/null +++ b/ambed/cfirfilter.h @@ -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 . +// ---------------------------------------------------------------------------- +// 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 + diff --git a/ambed/cfixedgain.cpp b/ambed/cfixedgain.cpp new file mode 100644 index 0000000..600df13 --- /dev/null +++ b/ambed/cfixedgain.cpp @@ -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 . +// ---------------------------------------------------------------------------- +// Geoffrey Merck F4FXL / KC3FRA AGC + +#include "cfixedgain.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// 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); + } +} \ No newline at end of file diff --git a/ambed/cfixedgain.h b/ambed/cfixedgain.h new file mode 100644 index 0000000..eadac47 --- /dev/null +++ b/ambed/cfixedgain.h @@ -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 . +// ---------------------------------------------------------------------------- +// 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 */ \ No newline at end of file diff --git a/ambed/cftdidevicedescr.cpp b/ambed/cftdidevicedescr.cpp index 71cbfbf..e17f4e8 100644 --- a/ambed/cftdidevicedescr.cpp +++ b/ambed/cftdidevicedescr.cpp @@ -24,6 +24,10 @@ #include "main.h" #include +#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*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*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*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*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*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*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*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*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; +} diff --git a/ambed/cftdidevicedescr.h b/ambed/cftdidevicedescr.h index acbc1bd..15fa362 100644 --- a/ambed/cftdidevicedescr.h +++ b/ambed/cftdidevicedescr.h @@ -27,6 +27,7 @@ #include #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*); + static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector*); + // 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*); + static int CreateUsb3006(CFtdiDeviceDescr *, std::vector*); + static int CreateUsb3003(CFtdiDeviceDescr *, std::vector*); + static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector*); + static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector*); + static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector*); + static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *); + static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *); + protected: // status bool m_bUsed; diff --git a/ambed/cpacket.h b/ambed/cpacket.h index cd30d6a..a7768c0 100644 --- a/ambed/cpacket.h +++ b/ambed/cpacket.h @@ -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 diff --git a/ambed/csampleblockprocessor.h b/ambed/csampleblockprocessor.h new file mode 100644 index 0000000..2c57f5f --- /dev/null +++ b/ambed/csampleblockprocessor.h @@ -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 . +// ---------------------------------------------------------------------------- +// 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 */ \ No newline at end of file diff --git a/ambed/csignalprocessor.cpp b/ambed/csignalprocessor.cpp new file mode 100644 index 0000000..21fba81 --- /dev/null +++ b/ambed/csignalprocessor.cpp @@ -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 . +// ---------------------------------------------------------------------------- +// 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); + }*/ +} \ No newline at end of file diff --git a/ambed/csignalprocessor.h b/ambed/csignalprocessor.h new file mode 100644 index 0000000..a1081d7 --- /dev/null +++ b/ambed/csignalprocessor.h @@ -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 . +// ---------------------------------------------------------------------------- +// Geoffrey Merck F4FXL / KC3FRA + +#ifndef csignalprocessor_h +#define csignalprocessor_h + +#include +#include "csampleblockprocessor.h" + +class CSignalProcessor +{ +public: + //Constructor + CSignalProcessor(float gaindB); + + //Destructor + ~CSignalProcessor(); + + //Processing + void Process(uint8* voice, int length); + +private: + std::vector m_sampleProcessors; +}; + +#endif /* csignalprocessor_h */ \ No newline at end of file diff --git a/ambed/cstream.cpp b/ambed/cstream.cpp index feb3cac..b9bfd16 100644 --- a/ambed/cstream.cpp +++ b/ambed/cstream.cpp @@ -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; } diff --git a/ambed/cusb3000interface.cpp b/ambed/cusb3000interface.cpp index 3cd0754..b340cba 100644 --- a/ambed/cusb3000interface.cpp +++ b/ambed/cusb3000interface.cpp @@ -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)) ) diff --git a/ambed/cusb3003df2etinterface.cpp b/ambed/cusb3003df2etinterface.cpp new file mode 100644 index 0000000..94cd357 --- /dev/null +++ b/ambed/cusb3003df2etinterface.cpp @@ -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 . +// ---------------------------------------------------------------------------- +// 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; +} + diff --git a/ambed/cusb3003df2etinterface.h b/ambed/cusb3003df2etinterface.h new file mode 100644 index 0000000..ad11cc3 --- /dev/null +++ b/ambed/cusb3003df2etinterface.h @@ -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 . +// ---------------------------------------------------------------------------- + +#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 */ diff --git a/ambed/cusb3003hrinterface.cpp b/ambed/cusb3003hrinterface.cpp new file mode 100644 index 0000000..f096d85 --- /dev/null +++ b/ambed/cusb3003hrinterface.cpp @@ -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 . +// ---------------------------------------------------------------------------- + +#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; +} + diff --git a/ambed/cusb3003hrinterface.h b/ambed/cusb3003hrinterface.h new file mode 100644 index 0000000..b045e14 --- /dev/null +++ b/ambed/cusb3003hrinterface.h @@ -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 . +// ---------------------------------------------------------------------------- + +#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 */ diff --git a/ambed/cusb3003interface.cpp b/ambed/cusb3003interface.cpp index e10361d..471dc39 100644 --- a/ambed/cusb3003interface.cpp +++ b/ambed/cusb3003interface.cpp @@ -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 diff --git a/ambed/cusb3003interface.h b/ambed/cusb3003interface.h index 2be4f57..984130e 100644 --- a/ambed/cusb3003interface.h +++ b/ambed/cusb3003interface.h @@ -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]; diff --git a/ambed/cusb3xxxinterface.cpp b/ambed/cusb3xxxinterface.cpp index b59e3fe..a27bc2b 100644 --- a/ambed/cusb3xxxinterface.cpp +++ b/ambed/cusb3xxxinterface.cpp @@ -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; diff --git a/ambed/cusb3xxxinterface.h b/ambed/cusb3xxxinterface.h index 31bf3c4..682d486 100644 --- a/ambed/cusb3xxxinterface.h +++ b/ambed/cusb3xxxinterface.h @@ -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 m_SpeechQueues; + std::vector m_ChannelQueues; + CPacketQueue m_DeviceQueue; + int m_iSpeechFifolLevel; + int m_iChannelFifolLevel; + CTimePoint m_SpeechFifoLevelTimeout; + CTimePoint m_ChannelFifoLevelTimeout; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvocodecchannel.cpp b/ambed/cvocodecchannel.cpp index 0212424..29a6fbd 100644 --- a/ambed/cvocodecchannel.cpp +++ b/ambed/cvocodecchannel.cpp @@ -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 diff --git a/ambed/cvocodecchannel.h b/ambed/cvocodecchannel.h index 4848c87..9726b9d 100644 --- a/ambed/cvocodecchannel.h +++ b/ambed/cvocodecchannel.h @@ -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; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvocodecinterface.h b/ambed/cvocodecinterface.h index 66f8fbb..18484d3 100644 --- a/ambed/cvocodecinterface.h +++ b/ambed/cvocodecinterface.h @@ -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; } diff --git a/ambed/cvocodecs.cpp b/ambed/cvocodecs.cpp index ca6ec71..c9e4643 100644 --- a/ambed/cvocodecs.cpp +++ b/ambed/cvocodecs.cpp @@ -24,8 +24,6 @@ #include "main.h" #include -#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 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 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 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 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 diff --git a/ambed/cvocodecs.h b/ambed/cvocodecs.h index 6688ebb..62da1f6 100644 --- a/ambed/cvocodecs.h +++ b/ambed/cvocodecs.h @@ -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 diff --git a/ambed/cvoicepacket.cpp b/ambed/cvoicepacket.cpp index 0fc05f7..3cfb66e 100644 --- a/ambed/cvoicepacket.cpp +++ b/ambed/cvoicepacket.cpp @@ -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); - } -} diff --git a/ambed/cvoicepacket.h b/ambed/cvoicepacket.h index 7189d01..bb8e6ce 100644 --- a/ambed/cvoicepacket.h +++ b/ambed/cvoicepacket.h @@ -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; diff --git a/ambed/main.cpp b/ambed/main.cpp index 6892471..c9363e2 100644 --- a/ambed/main.cpp +++ b/ambed/main.cpp @@ -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 diff --git a/ambed/main.h b/ambed/main.h index 4c14244..118dcfb 100644 --- a/ambed/main.h +++ b/ambed/main.h @@ -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 diff --git a/ambed/makefile b/ambed/makefile index 0aa514e..c556a28 100644 --- a/ambed/makefile +++ b/ambed/makefile @@ -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/ diff --git a/ambed/readme b/ambed/readme index 3c6713a..6bdbca1 100644 --- a/ambed/readme +++ b/ambed/readme @@ -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 . // ---------------------------------------------------------------------------- +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 diff --git a/ambedtest/ccodecstream.cpp b/ambedtest/ccodecstream.cpp index 5910f8d..5c5fcf3 100644 --- a/ambedtest/ccodecstream.cpp +++ b/ambedtest/ccodecstream.cpp @@ -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; } diff --git a/ambedtest/ccodecstream.h b/ambedtest/ccodecstream.h index 568e466..4619648 100644 --- a/ambedtest/ccodecstream.h +++ b/ambedtest/ccodecstream.h @@ -99,6 +99,7 @@ protected: std::thread *m_pThread; CTimePoint m_TimeoutTimer; CTimePoint m_FrameTimer; + uint32 m_uiNbTotalPacketSent; // stats CTimePoint m_StatsTimer; diff --git a/ambedtest/makefile b/ambedtest/makefile index 9e795b1..bc1a804 100644 --- a/ambedtest/makefile +++ b/ambedtest/makefile @@ -14,4 +14,4 @@ $(EXECUTABLE): $(OBJECTS) $(CC) $(CFLAGS) $< -o $@ clean: - $(RM) *.o + $(RM) $(EXECUTABLE) *.o diff --git a/config/xlxd.terminal b/config/xlxd.terminal new file mode 100644 index 0000000..e8b0cf5 --- /dev/null +++ b/config/xlxd.terminal @@ -0,0 +1,17 @@ +######################################################################################### +# XLXD terminal option file +# +# one line per entry +# each entry specifies a terminal option +# +# Valid option: +# address - 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 - a string with all modules to accept a terminal connection +# Default value is "*", meaning accept all +# +######################################################################################### +#address 193.1.2.3 +#modules BCD diff --git a/dashboard/changes.txt b/dashboard/changes.txt index 727e0b5..5d18d53 100755 --- a/dashboard/changes.txt +++ b/dashboard/changes.txt @@ -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 server’s /tmp folder. +On the first run your personal hash to access the database is place in the server’s /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 diff --git a/dashboard/css/layout.css b/dashboard/css/layout.css index 3a80aff..700668b 100755 --- a/dashboard/css/layout.css +++ b/dashboard/css/layout.css @@ -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; } diff --git a/dashboard/img/flags/ai.png b/dashboard/img/flags/ai.png deleted file mode 100644 index 5f3805b..0000000 Binary files a/dashboard/img/flags/ai.png and /dev/null differ diff --git a/dashboard/img/flags/as.png b/dashboard/img/flags/as.png deleted file mode 100644 index 642fb42..0000000 Binary files a/dashboard/img/flags/as.png and /dev/null differ diff --git a/dashboard/img/flags/aw.png b/dashboard/img/flags/aw.png deleted file mode 100644 index 129032c..0000000 Binary files a/dashboard/img/flags/aw.png and /dev/null differ diff --git a/dashboard/img/flags/bl.png b/dashboard/img/flags/bl.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/bl.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/bm.png b/dashboard/img/flags/bm.png deleted file mode 100644 index 292f97b..0000000 Binary files a/dashboard/img/flags/bm.png and /dev/null differ diff --git a/dashboard/img/flags/bv.png b/dashboard/img/flags/bv.png deleted file mode 120000 index a254bed..0000000 --- a/dashboard/img/flags/bv.png +++ /dev/null @@ -1 +0,0 @@ -no.png \ No newline at end of file diff --git a/dashboard/img/flags/cc.png b/dashboard/img/flags/cc.png deleted file mode 100644 index ff140fc..0000000 Binary files a/dashboard/img/flags/cc.png and /dev/null differ diff --git a/dashboard/img/flags/ck.png b/dashboard/img/flags/ck.png deleted file mode 100644 index 8756cc1..0000000 Binary files a/dashboard/img/flags/ck.png and /dev/null differ diff --git a/dashboard/img/flags/cw.png b/dashboard/img/flags/cw.png deleted file mode 100644 index dbbc656..0000000 Binary files a/dashboard/img/flags/cw.png and /dev/null differ diff --git a/dashboard/img/flags/cx.png b/dashboard/img/flags/cx.png deleted file mode 100644 index bc39174..0000000 Binary files a/dashboard/img/flags/cx.png and /dev/null differ diff --git a/dashboard/img/flags/en.png b/dashboard/img/flags/en.png new file mode 100644 index 0000000..f87a2ac Binary files /dev/null and b/dashboard/img/flags/en.png differ diff --git a/dashboard/img/flags/fk.png b/dashboard/img/flags/fk.png deleted file mode 100644 index e8e761b..0000000 Binary files a/dashboard/img/flags/fk.png and /dev/null differ diff --git a/dashboard/img/flags/fo.png b/dashboard/img/flags/fo.png deleted file mode 100644 index d101593..0000000 Binary files a/dashboard/img/flags/fo.png and /dev/null differ diff --git a/dashboard/img/flags/gf.png b/dashboard/img/flags/gf.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/gf.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/gg.png b/dashboard/img/flags/gg.png deleted file mode 100644 index f6264d2..0000000 Binary files a/dashboard/img/flags/gg.png and /dev/null differ diff --git a/dashboard/img/flags/gi.png b/dashboard/img/flags/gi.png deleted file mode 100644 index 3209126..0000000 Binary files a/dashboard/img/flags/gi.png and /dev/null differ diff --git a/dashboard/img/flags/gl.png b/dashboard/img/flags/gl.png deleted file mode 100644 index 9aaa281..0000000 Binary files a/dashboard/img/flags/gl.png and /dev/null differ diff --git a/dashboard/img/flags/gp.png b/dashboard/img/flags/gp.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/gp.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/gs.png b/dashboard/img/flags/gs.png deleted file mode 100644 index c24edc6..0000000 Binary files a/dashboard/img/flags/gs.png and /dev/null differ diff --git a/dashboard/img/flags/hm.png b/dashboard/img/flags/hm.png deleted file mode 120000 index 79a4a52..0000000 --- a/dashboard/img/flags/hm.png +++ /dev/null @@ -1 +0,0 @@ -au.png \ No newline at end of file diff --git a/dashboard/img/flags/io.png b/dashboard/img/flags/io.png deleted file mode 100644 index 24d6767..0000000 Binary files a/dashboard/img/flags/io.png and /dev/null differ diff --git a/dashboard/img/flags/je.png b/dashboard/img/flags/je.png deleted file mode 100644 index 80dcf75..0000000 Binary files a/dashboard/img/flags/je.png and /dev/null differ diff --git a/dashboard/img/flags/jp.png b/dashboard/img/flags/jp.png index fd1ce05..c1b7aac 100755 Binary files a/dashboard/img/flags/jp.png and b/dashboard/img/flags/jp.png differ diff --git a/dashboard/img/flags/ky.png b/dashboard/img/flags/ky.png deleted file mode 100644 index 298a5d1..0000000 Binary files a/dashboard/img/flags/ky.png and /dev/null differ diff --git a/dashboard/img/flags/mf.png b/dashboard/img/flags/mf.png deleted file mode 100644 index 2e203d1..0000000 Binary files a/dashboard/img/flags/mf.png and /dev/null differ diff --git a/dashboard/img/flags/mp.png b/dashboard/img/flags/mp.png deleted file mode 100644 index d6733d6..0000000 Binary files a/dashboard/img/flags/mp.png and /dev/null differ diff --git a/dashboard/img/flags/mq.png b/dashboard/img/flags/mq.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/mq.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/ms.png b/dashboard/img/flags/ms.png deleted file mode 100644 index 516430e..0000000 Binary files a/dashboard/img/flags/ms.png and /dev/null differ diff --git a/dashboard/img/flags/nc.png b/dashboard/img/flags/nc.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/nc.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/nf.png b/dashboard/img/flags/nf.png deleted file mode 100644 index 8e5a705..0000000 Binary files a/dashboard/img/flags/nf.png and /dev/null differ diff --git a/dashboard/img/flags/nu.png b/dashboard/img/flags/nu.png deleted file mode 100644 index f3e621c..0000000 Binary files a/dashboard/img/flags/nu.png and /dev/null differ diff --git a/dashboard/img/flags/pf.png b/dashboard/img/flags/pf.png deleted file mode 100644 index 13618ce..0000000 Binary files a/dashboard/img/flags/pf.png and /dev/null differ diff --git a/dashboard/img/flags/pm.png b/dashboard/img/flags/pm.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/pm.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/pn.png b/dashboard/img/flags/pn.png deleted file mode 100644 index 566166f..0000000 Binary files a/dashboard/img/flags/pn.png and /dev/null differ diff --git a/dashboard/img/flags/ps.png b/dashboard/img/flags/ps.png deleted file mode 100644 index 6232014..0000000 Binary files a/dashboard/img/flags/ps.png and /dev/null differ diff --git a/dashboard/img/flags/ss.png b/dashboard/img/flags/ss.png deleted file mode 100644 index d60fe1a..0000000 Binary files a/dashboard/img/flags/ss.png and /dev/null differ diff --git a/dashboard/img/flags/sx.png b/dashboard/img/flags/sx.png deleted file mode 100644 index c3f90d4..0000000 Binary files a/dashboard/img/flags/sx.png and /dev/null differ diff --git a/dashboard/img/flags/tc.png b/dashboard/img/flags/tc.png deleted file mode 100644 index 0f91d4d..0000000 Binary files a/dashboard/img/flags/tc.png and /dev/null differ diff --git a/dashboard/img/flags/tk.png b/dashboard/img/flags/tk.png deleted file mode 100644 index e48e1f4..0000000 Binary files a/dashboard/img/flags/tk.png and /dev/null differ diff --git a/dashboard/img/flags/um.png b/dashboard/img/flags/um.png deleted file mode 120000 index ea19c57..0000000 --- a/dashboard/img/flags/um.png +++ /dev/null @@ -1 +0,0 @@ -us.png \ No newline at end of file diff --git a/dashboard/img/flags/vg.png b/dashboard/img/flags/vg.png deleted file mode 100644 index d4ba827..0000000 Binary files a/dashboard/img/flags/vg.png and /dev/null differ diff --git a/dashboard/img/flags/vi.png b/dashboard/img/flags/vi.png deleted file mode 100644 index 2e53061..0000000 Binary files a/dashboard/img/flags/vi.png and /dev/null differ diff --git a/dashboard/img/flags/wf.png b/dashboard/img/flags/wf.png deleted file mode 120000 index e916a05..0000000 --- a/dashboard/img/flags/wf.png +++ /dev/null @@ -1 +0,0 @@ -fr.png \ No newline at end of file diff --git a/dashboard/img/flags/yt.png b/dashboard/img/flags/yt.png deleted file mode 100644 index 17e788b..0000000 Binary files a/dashboard/img/flags/yt.png and /dev/null differ diff --git a/dashboard/index.php b/dashboard/index.php index 6509be5..19b8833 100755 --- a/dashboard/index.php +++ b/dashboard/index.php @@ -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, "'); - @fclose($Ressource); - @exec("chmod 777 ".$CallingHome['HashFile']); - $CallHomeNow = true; - } + $Ressource = fopen($CallingHome['HashFile'], "w+"); + if ($Ressource) { + $Hash = CreateCode(16); + @fwrite($Ressource, "'); + @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, "'); - @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 = ""; } - - -?> @@ -84,25 +94,32 @@ else { if ($PageOptions['PageRefreshActive']) { echo ' + '; } @@ -113,12 +130,32 @@ else {
XLX Multiprotocol Gateway Reflector -
   GetReflectorName(); ?> vGetVersion(); ?> - Dashboard v  /  Service uptime: GetServiceUptime()); ?>
+
   GetReflectorName(); ?> vGetVersion(); ?> - Dashboard v   /  Service uptime: GetServiceUptime()); ?>