ambed version 1.0.0

added amber version 1.0.0
This commit is contained in:
LX3JL 2017-08-09 13:26:01 +02:00
parent 9eb47b28c1
commit 0b5f1fbdd4
44 changed files with 6687 additions and 0 deletions

154
ambed/WinTypes.h Executable file
View File

@ -0,0 +1,154 @@
#ifndef __WINDOWS_TYPES__
#define __WINDOWS_TYPES__
#define WINAPI
typedef unsigned int DWORD;
typedef unsigned int ULONG;
typedef unsigned short USHORT;
typedef unsigned short SHORT;
typedef unsigned char UCHAR;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
typedef unsigned char BYTE;
typedef BYTE *LPBYTE;
typedef unsigned int BOOL;
typedef unsigned char BOOLEAN;
typedef unsigned char CHAR;
typedef BOOL *LPBOOL;
typedef UCHAR *PUCHAR;
typedef const char *LPCSTR;
typedef char *PCHAR;
typedef void *PVOID;
typedef void *HANDLE;
typedef unsigned int LONG;
typedef int INT;
typedef unsigned int UINT;
typedef char *LPSTR;
typedef char *LPTSTR;
typedef const char *LPCTSTR;
typedef DWORD *LPDWORD;
typedef WORD *LPWORD;
typedef ULONG *PULONG;
typedef LONG *LPLONG;
typedef PVOID LPVOID;
typedef void VOID;
typedef USHORT *PUSHORT;
typedef unsigned long long int ULONGLONG;
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
union {
struct{
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
#include <pthread.h>
// Substitute for HANDLE returned by Windows CreateEvent API.
// FT_SetEventNotification expects parameter 3 to be the address
// of one of these structures.
typedef struct _EVENT_HANDLE
{
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
int iVar;
} EVENT_HANDLE;
typedef struct timeval SYSTEMTIME;
typedef struct timeval FILETIME;
// WaitForSingleObject return values.
#define WAIT_ABANDONED 0x00000080L
#define WAIT_OBJECT_0 0x00000000L
#define WAIT_TIMEOUT 0x00000102L
#define WAIT_FAILED 0xFFFFFFFF
// Special value for WaitForSingleObject dwMilliseconds parameter
#define INFINITE 0xFFFFFFFF // Infinite timeout
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef CONST
#define CONST const
#endif
//
// Modem Status Flags
//
#define MS_CTS_ON ((DWORD)0x0010)
#define MS_DSR_ON ((DWORD)0x0020)
#define MS_RING_ON ((DWORD)0x0040)
#define MS_RLSD_ON ((DWORD)0x0080)
//
// Error Flags
//
#define CE_RXOVER 0x0001 // Receive Queue overflow
#define CE_OVERRUN 0x0002 // Receive Overrun Error
#define CE_RXPARITY 0x0004 // Receive Parity Error
#define CE_FRAME 0x0008 // Receive Framing error
#define CE_BREAK 0x0010 // Break Detected
#define CE_TXFULL 0x0100 // TX Queue is full
#define CE_PTO 0x0200 // LPTx Timeout
#define CE_IOE 0x0400 // LPTx I/O Error
#define CE_DNS 0x0800 // LPTx Device not selected
#define CE_OOP 0x1000 // LPTx Out-Of-Paper
#define CE_MODE 0x8000 // Requested mode unsupported
//
// Events
//
#define EV_RXCHAR 0x0001 // Any Character received
#define EV_RXFLAG 0x0002 // Received certain character
#define EV_TXEMPTY 0x0004 // Transmit Queue Empty
#define EV_CTS 0x0008 // CTS changed state
#define EV_DSR 0x0010 // DSR changed state
#define EV_RLSD 0x0020 // RLSD changed state
#define EV_BREAK 0x0040 // BREAK received
#define EV_ERR 0x0080 // Line status error occurred
#define EV_RING 0x0100 // Ring signal detected
#define EV_PERR 0x0200 // Printer error occured
#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full
#define EV_EVENT1 0x0800 // Provider specific event 1
#define EV_EVENT2 0x1000 // Provider specific event 2
//
// Escape Functions
//
#define SETXOFF 1 // Simulate XOFF received
#define SETXON 2 // Simulate XON received
#define SETRTS 3 // Set RTS high
#define CLRRTS 4 // Set RTS low
#define SETDTR 5 // Set DTR high
#define CLRDTR 6 // Set DTR low
#define RESETDEV 7 // Reset device if possible
#define SETBREAK 8 // Set the device break line.
#define CLRBREAK 9 // Clear the device break line.
//
// PURGE function flags.
//
#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port.
#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port.
#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there.
#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there.
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
#endif
#endif /* __WINDOWS_TYPES__ */

71
ambed/cambepacket.cpp Normal file
View File

@ -0,0 +1,71 @@
//
// cambepacket.cpp
// ambed
//
// cpacketqueue.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cambepacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CAmbePacket::CAmbePacket()
{
m_uiCodec = CODEC_NONE;
::memset(m_uiAmbe, 0, AMBE_SIZE);
}
CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe)
: CPacket(uiPid)
{
m_uiCodec = uiCodec;
::memcpy(m_uiAmbe, Ambe, AMBE_SIZE);
}
CAmbePacket::CAmbePacket(const CAmbePacket &packet)
: CPacket(packet)
{
m_uiCodec = packet.m_uiCodec;
::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe));
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CAmbePacket::~CAmbePacket()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// Set
void CAmbePacket::SetAmbe(const uint8 *p)
{
::memcpy(m_uiAmbe, p, AMBE_SIZE);
}

67
ambed/cambepacket.h Normal file
View File

@ -0,0 +1,67 @@
//
// cambepacket.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cambepacket_h
#define cambepacket_h
#include "cpacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
// frame sizes
#define AMBE_SIZE 9
////////////////////////////////////////////////////////////////////////////////////////
// class
class CAmbePacket : public CPacket
{
public:
// constructors
CAmbePacket();
CAmbePacket(uint8, uint8, const uint8 *);
CAmbePacket(const CAmbePacket &);
// destructor
virtual ~CAmbePacket();
// get
uint8 GetCodec(void) const { return m_uiCodec; }
uint8 *GetAmbe(void) { return m_uiAmbe; }
int GetAmbeSize(void) const { return AMBE_SIZE; }
// set
void SetCodec(uint8 c) { m_uiCodec = c; }
void SetAmbe(const uint8 *);
protected:
// data
uint8 m_uiCodec;
uint8 m_uiAmbe[AMBE_SIZE];
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cambepacket_h */

125
ambed/cambeserver.cpp Normal file
View File

@ -0,0 +1,125 @@
//
// cambeserver.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "ccontroller.h"
#include "cvocodecs.h"
#include "cambeserver.h"
////////////////////////////////////////////////////////////////////////////////////////
CAmbeServer g_AmbeServer;
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CAmbeServer::CAmbeServer()
{
m_bStopThreads = false;
m_pThread = NULL;
#ifdef DEBUG_DUMPFILE
m_DebugFile.open("/Users/jeanluc/Desktop/ambed.txt");
#endif
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CAmbeServer::~CAmbeServer()
{
m_bStopThreads = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
}
#ifdef DEBUG_DUMPFILE
m_DebugFile.close();
#endif
}
////////////////////////////////////////////////////////////////////////////////////////
// operation
bool CAmbeServer::Start(void)
{
bool ok = true;
// init interfaces & controller
std::cout << "Initializing vocodecs:" << std::endl;
ok &= g_Vocodecs.Init();
std::cout << std::endl;
std::cout << "Initializing controller" << std::endl;
ok &= m_Controller.Init();
std::cout << std::endl;
// if ok, start threads
if ( ok )
{
//
m_pThread = new std::thread(CAmbeServer::Thread, this);
}
// done
return ok;
}
void CAmbeServer::Stop(void)
{
// stop controller
m_Controller.Close();
// stop & delete all threads
m_bStopThreads = true;
// stop & delete report threads
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CAmbeServer::Thread(CAmbeServer *This)
{
while ( !This->m_bStopThreads )
{
This->Task();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CAmbeServer::Task(void)
{
// and wait a bit
CTimePoint::TaskSleepFor(10000);
}

76
ambed/cambeserver.h Normal file
View File

@ -0,0 +1,76 @@
//
// cambeserver.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cambeserver_h
#define cambeserver_h
#include "ccontroller.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CAmbeServer
{
public:
// constructors
CAmbeServer();
// destructor
virtual ~CAmbeServer();
// operation
bool Start(void);
void Stop(void);
// task
static void Thread(CAmbeServer *);
void Task(void);
// get
const CIp &GetListenIp(void) const { return m_Controller.GetListenIp(); }
// set
void SetListenIp(const CIp &ip) { m_Controller.SetListenIp(ip); }
// operator
//bool operator ==(const CIp &) const;
//operator const char *() const;
protected:
// objects
CController m_Controller;
// threads
bool m_bStopThreads;
std::thread *m_pThread;
public:
#ifdef DEBUG_DUMPFILE
std::ofstream m_DebugFile;
#endif
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cambeserver_h */

200
ambed/cbuffer.cpp Normal file
View File

@ -0,0 +1,200 @@
//
// cbuffer.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cbuffer.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CBuffer::CBuffer(uint8 *buffer, int len)
{
resize(len);
::memcpy(data(), buffer, len);
}
////////////////////////////////////////////////////////////////////////////////////////
// set
void CBuffer::Set(uint8 *buffer, int len)
{
resize(len);
::memcpy(data(), buffer, len);
}
void CBuffer::Set(const char *sz)
{
resize(::strlen(sz)+1);
::strcpy((char *)data(), sz);
}
void CBuffer::Append(uint8 *buffer, int len)
{
int n = (int)size();
resize(n+len);
::memcpy(&(data()[n]), buffer, len);
}
void CBuffer::Append(uint8 ui, int len)
{
int n = (int)size();
resize(n+len);
::memset(&(data()[n]), ui, len);
}
void CBuffer::Append(uint8 ui)
{
int n = (int)size();
resize(n+sizeof(uint8));
::memcpy(&(data()[n]), &ui, sizeof(uint8));
}
void CBuffer::Append(uint16 ui)
{
int n = (int)size();
resize(n+sizeof(uint16));
::memcpy(&(data()[n]), &ui, sizeof(uint16));
}
void CBuffer::Append(uint32 ui)
{
int n = (int)size();
resize(n+sizeof(uint32));
::memcpy(&(data()[n]), &ui, sizeof(uint32));
}
void CBuffer::Append(const char *sz)
{
Append((uint8 *)sz, (int)strlen(sz));
Append((uint8)0x00);
}
void CBuffer::ReplaceAt(int i, uint8 ui)
{
if ( size() < (i+sizeof(uint8)) )
{
resize(i+sizeof(uint8));
}
*(uint8 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, uint16 ui)
{
if ( size() < (i+sizeof(uint16)) )
{
resize(i+sizeof(uint16));
}
*(uint16 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, uint32 ui)
{
if ( size() < (i+sizeof(uint32)) )
{
resize(i+sizeof(uint32));
}
*(uint32 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len)
{
if ( size() < (i+len) )
{
resize(i+len);
}
::memcpy(&(data()[i]), ptr, len);
}
////////////////////////////////////////////////////////////////////////////////////////
// operation
int CBuffer::Compare(uint8 *buffer, int len) const
{
int result = -1;
if ( size() >= len )
{
result = ::memcmp(data(), buffer, len);
}
return result;
}
int CBuffer::Compare(uint8 *buffer, int off, int len) const
{
int result = -1;
if ( size() >= (off+len) )
{
result = ::memcmp(&(data()[off]), buffer, len);
}
return result;
}
////////////////////////////////////////////////////////////////////////////////////////
// operator
bool CBuffer::operator ==(const CBuffer &Buffer) const
{
if ( size() == Buffer.size() )
{
return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0);
}
return false;
}
bool CBuffer::operator ==(const char *sz) const
{
if ( size() == ::strlen(sz) )
{
return (::memcmp((const char *)data(), sz, size()) == 0);
}
return false;
}
CBuffer::operator const char *() const
{
return (const char *)data();
}
////////////////////////////////////////////////////////////////////////////////////////
// debug
void CBuffer::DebugDump(std::ofstream &debugout)
{
for ( int i = 0; i < size(); i++ )
{
char sz[16];
sprintf(sz, "%02X", data()[i]);
debugout << sz;
if ( i == size()-1 )
{
debugout << std::endl;
}
else
{
debugout << ',';
}
}
}

68
ambed/cbuffer.h Normal file
View File

@ -0,0 +1,68 @@
//
// cbuffer.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cbuffer_h
#define cbuffer_h
////////////////////////////////////////////////////////////////////////////////////////
class CBuffer : public std::vector<uint8>
{
public:
// constructor
CBuffer() {};
CBuffer(uint8 *, int);
// destructor
virtual ~CBuffer() {};
// set
void Set(uint8 *, int);
void Set(const char *);
void Append(uint8 *, int);
void Append(uint8, int);
void Append(uint8);
void Append(uint16);
void Append(uint32);
void Append(const char *);
void ReplaceAt(int, uint8);
void ReplaceAt(int, uint16);
void ReplaceAt(int, uint32);
void ReplaceAt(int, const uint8 *, int);
// operation
int Compare(uint8 *, int) const;
int Compare(uint8 *, int, int) const;
// operator
bool operator ==(const CBuffer &) const;
bool operator ==(const char *) const;
operator const char *() const;
// debug
void DebugDump(std::ofstream &);
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cbuffer_h */

198
ambed/ccallsign.cpp Normal file
View File

@ -0,0 +1,198 @@
//
// ccallsign.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include <cctype>
#include "ccallsign.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructors
CCallsign::CCallsign()
{
// blank all
::memset(m_Callsign, ' ', sizeof(m_Callsign));
}
CCallsign::CCallsign(const char *sz)
{
::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)));
}
CCallsign::CCallsign(const CCallsign &callsign)
{
::memcpy(m_Callsign, callsign.m_Callsign, sizeof(m_Callsign));
}
////////////////////////////////////////////////////////////////////////////////////////
// status
bool CCallsign::IsValid(void) const
{
bool valid = true;
int i;
// callsign
// first 3 chars are letter or number but cannot be all number
int iNum = 0;
for ( i = 0; i < 3; i++ )
{
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]);
if ( IsNumber(m_Callsign[i]) )
{
iNum++;
}
}
valid &= (iNum < 3);
// all remaining char are letter, number or space
for ( ; i < CALLSIGN_LEN; i++)
{
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]);
}
// done
return valid;
}
////////////////////////////////////////////////////////////////////////////////////////
// set
void CCallsign::SetCallsign(const char *sz)
{
// set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)));
}
void CCallsign::SetCallsign(const uint8 *buffer, int len)
{
// set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)));
for ( int i = 0; i < sizeof(m_Callsign); i++ )
{
if ( m_Callsign[i] == 0 )
{
m_Callsign[i] = ' ';
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
// modify
void CCallsign::PatchCallsign(int off, const uint8 *patch, int len)
{
if ( off < sizeof(m_Callsign) )
{
::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off));
}
}
////////////////////////////////////////////////////////////////////////////////////////
// get
void CCallsign::GetCallsign(uint8 *buffer) const
{
::memcpy(buffer, m_Callsign, sizeof(m_Callsign));
}
void CCallsign::GetCallsignString(char *sz) const
{
int i;
for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ )
{
sz[i] = m_Callsign[i];
}
sz[i] = 0;
}
////////////////////////////////////////////////////////////////////////////////////////
// compare
bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const
{
return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0);
}
bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const
{
bool same = true;
bool done = false;
for ( int i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ )
{
if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) )
{
same &= (m_Callsign[i] == callsign[i]);
}
}
return same;
}
////////////////////////////////////////////////////////////////////////////////////////
// operators
bool CCallsign::operator ==(const CCallsign &callsign) const
{
return (::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0);
}
CCallsign::operator const char *() const
{
char *sz = (char *)(const char *)m_sz;
// empty
::memset(sz, 0, sizeof(m_sz));
// callsign
sz[CALLSIGN_LEN] = 0;
::memcpy(sz, m_Callsign, sizeof(m_Callsign));
// done
return m_sz;
}
////////////////////////////////////////////////////////////////////////////////////////
// helper
bool CCallsign::IsNumber(char c) const
{
return ((c >= '0') && (c <= '9'));
}
bool CCallsign::IsLetter(char c) const
{
return ((c >= 'A') && (c <= 'Z'));
}
bool CCallsign::IsSpace(char c) const
{
return (c == ' ');
}

83
ambed/ccallsign.h Normal file
View File

@ -0,0 +1,83 @@
//
// ccallsign.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef ccallsign_h
#define ccallsign_h
////////////////////////////////////////////////////////////////////////////////////////
// define
#define CALLSIGN_LEN 8
////////////////////////////////////////////////////////////////////////////////////////
// class
class CCallsign
{
public:
// contructors
CCallsign();
CCallsign(const char *);
CCallsign(const CCallsign &);
// destructor
virtual ~CCallsign() {};
// status
bool IsValid(void) const;
// set
void SetCallsign(const char *);
void SetCallsign(const uint8 *, int);
// modify
void PatchCallsign(int, const uint8 *, int);
// get
void GetCallsign(uint8 *) const;
void GetCallsignString(char *) const;
// compare
bool HasSameCallsign(const CCallsign &) const;
bool HasSameCallsignWithWildcard(const CCallsign &) const;
// operators
bool operator ==(const CCallsign &) const;
operator const char *() const;
protected:
// helper
bool IsNumber(char) const;
bool IsLetter(char) const;
bool IsSpace(char) const;
protected:
// data
char m_Callsign[CALLSIGN_LEN];
char m_sz[CALLSIGN_LEN+1];
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* ccallsign_h */

373
ambed/ccontroller.cpp Normal file
View File

@ -0,0 +1,373 @@
//
// ccontroller.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cvocodecs.h"
#include "ccontroller.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CController::CController()
{
m_bStopThread = false;
m_pThread = NULL;
m_Ip = CIp("127.0.0.1");
m_uiLastStreamId = 0;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CController::~CController()
{
// close socket
m_Socket.Close();
// close all streams
m_Mutex.lock();
{
for ( int i = 0; i < m_Streams.size(); i++ )
{
delete m_Streams[i];
}
m_Streams.clear();
}
m_Mutex.unlock();
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CController::Init(void)
{
bool ok;
// reset stop flag
m_bStopThread = false;
// create our socket
ok = m_Socket.Open(m_Ip, TRANSCODER_PORT);
if ( ok )
{
// start thread;
m_pThread = new std::thread(CController::Thread, this);
}
else
{
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl;
}
// done
return true;
}
void CController::Close(void)
{
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CController::Thread(CController *This)
{
while ( !This->m_bStopThread )
{
This->Task();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CController::Task(void)
{
CBuffer Buffer;
CIp Ip;
CCallsign Callsign;
uint8 CodecIn;
uint8 CodecOut;
uint16 StreamId;
CStream *Stream;
// anything coming in from codec client ?
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
{
// crack packet
if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) )
{
std::cout << "Stream Open from " << Callsign << std::endl;
// try create the stream
Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut);
// send back details
if ( Stream != NULL )
{
EncodeStreamDescrPacket(&Buffer, *Stream);
}
else
{
EncodeNoStreamAvailablePacket(&Buffer);
}
m_Socket.Send(Buffer, Ip);
}
else if ( IsValidClosestreamPacket(Buffer, &StreamId) )
{
// close the stream
CloseStream(StreamId);
std::cout << "Stream " << (int)StreamId << " closed" << std::endl;
}
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{
//std::cout << "ping - " << Callsign << std::endl;
// pong back
EncodeKeepAlivePacket(&Buffer);
m_Socket.Send(Buffer, Ip);
}
}
// HandleTimout/keepalive
bool timeout;
do
{
// init loop stuffs
timeout = false;
CStream *stream = NULL;
// any inactive streams?
Lock();
{
for ( int i = 0; (i < m_Streams.size()) && !timeout; i++ )
{
if ( !(m_Streams[i]->IsActive()) )
{
timeout = true;
stream = m_Streams[i];
std::cout << "Stream " << (int)m_Streams[i]->GetId() << " activity timeout " << std::endl;
}
}
}
Unlock();
// if any streams timeout, close it
// this cannot be done in above loop as it suppress it from array
if ( timeout )
{
CloseStream(stream);
}
} while (timeout);
}
////////////////////////////////////////////////////////////////////////////////////////
// streams management
CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut)
{
CStream *stream = NULL;
// create a new stream
m_uiLastStreamId = (m_uiLastStreamId + 1);
m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId;
stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut);
if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) )
{
std::cout << "Opened stream " << m_uiLastStreamId << std::endl;
// and store it
Lock();
m_Streams.push_back(stream);
Unlock();
}
else
{
delete stream;
stream = NULL;
}
// done
return stream;
}
void CController::CloseStream(CStream *stream)
{
Lock();
{
// look for the stream
bool found = false;
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
{
// compare object pointers
if ( (m_Streams[i]) == stream )
{
// close it
m_Streams[i]->Close();
// remove it
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
delete m_Streams[i];
m_Streams.erase(m_Streams.begin()+i);
found = true;
}
}
}
Unlock();
}
void CController::CloseStream(uint16 StreamId)
{
Lock();
{
// look for the stream
bool found = false;
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
{
// compare object pointers
if ( (m_Streams[i]->GetId()) == StreamId )
{
// close it
m_Streams[i]->Close();
// remove it
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
delete m_Streams[i];
m_Streams.erase(m_Streams.begin()+i);
found = true;
}
}
}
Unlock();
}
////////////////////////////////////////////////////////////////////////////////////////
// packet decoding helpers
bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign)
{
uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' };
bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{
// get callsign here
Callsign->SetCallsign(&(Buffer.data()[9]), 8);
valid = Callsign->IsValid();
}
return valid;
}
bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut)
{
uint8 tag[] = { 'A','M','B','E','D','O','S' };
bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{
// get callsign here
Callsign->SetCallsign(&(Buffer.data()[7]), 8);
*CodecIn = Buffer.data()[15];
*CodecOut = Buffer.data()[16];
// valid ?
valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut);
}
return valid;
}
bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId)
{
uint8 tag[] = { 'A','M','B','E','D','C','S' };
bool valid = false;
if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) )
{
// get stream id
*StreamId = *(uint16 *)(&Buffer.data()[7]);
valid = true;
}
return valid;
}
////////////////////////////////////////////////////////////////////////////////////////
// packet encoding helpers
void CController::EncodeKeepAlivePacket(CBuffer *Buffer)
{
uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' };
Buffer->Set(tag, sizeof(tag));
}
void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream)
{
uint8 tag[] = { 'A','M','B','E','D','S','T','D' };
Buffer->Set(tag, sizeof(tag));
// id
Buffer->Append((uint16)Stream.GetId());
// port
Buffer->Append((uint16)Stream.GetPort());
// codecin
Buffer->Append((uint8)Stream.GetCodecIn());
// codecout
Buffer->Append((uint8)Stream.GetCodecOut());
}
void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer)
{
uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' };
Buffer->Set(tag, sizeof(tag));
}
////////////////////////////////////////////////////////////////////////////////////////
// codec helpers
bool CController::IsValidCodecIn(uint8 codec)
{
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
}
bool CController::IsValidCodecOut(uint8 codec)
{
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
}

98
ambed/ccontroller.h Normal file
View File

@ -0,0 +1,98 @@
//
// ccontroller.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef ccontroller_h
#define ccontroller_h
#include "ccallsign.h"
#include "cstream.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CController
{
public:
// constructors
CController();
// destructor
virtual ~CController();
// initialization
bool Init(void);
void Close(void);
// locks
void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); }
// get
const CIp &GetListenIp(void) const { return (const CIp &)m_Ip; }
// set
void SetListenIp(const CIp &ip) { m_Ip = ip; }
// streams management
CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8);
void CloseStream(CStream *);
void CloseStream(uint16);
// task
static void Thread(CController *);
void Task(void);
protected:
// packet decoding helpers
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *);
bool IsValidClosestreamPacket(const CBuffer &, uint16 *);
// packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *);
void EncodeStreamDescrPacket(CBuffer *, const CStream &);
void EncodeNoStreamAvailablePacket(CBuffer *);
// codec helpers
bool IsValidCodecIn(uint8);
bool IsValidCodecOut(uint8);
protected:
// control socket
CIp m_Ip;
CUdpSocket m_Socket;
// streams
uint16 m_uiLastStreamId;
std::mutex m_Mutex;
std::vector<CStream *> m_Streams;
// thread
bool m_bStopThread;
std::thread *m_pThread;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* ccontroller_h */

View File

@ -0,0 +1,58 @@
//
// cftdidevicedescr.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cftdidevicedescr.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CFtdiDeviceDescr::CFtdiDeviceDescr(void)
{
m_bUsed = false;
m_uiVid = 0;
m_uiPid = 0;
::memset(m_szDescription, 0, sizeof(m_szDescription));
::memset(m_szSerial, 0, sizeof(m_szSerial));
}
CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial)
{
m_bUsed = false;
m_uiVid = uiVid;
m_uiPid = uiPid;
::strcpy(m_szDescription, szDescription);
::strcpy(m_szSerial, szSerial);
}
CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr)
{
m_bUsed = descr.m_bUsed;
m_uiVid = descr.m_uiVid;
m_uiPid = descr.m_uiPid;
::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription));
::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial));
}

77
ambed/cftdidevicedescr.h Normal file
View File

@ -0,0 +1,77 @@
//
// cftdidevicedescr.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cftdidevicedescr_h
#define cftdidevicedescr_h
#include <string.h>
#include "ftd2xx.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
#define FTDI_MAX_STRINGLENGTH 256
////////////////////////////////////////////////////////////////////////////////////////
// class
class CFtdiDeviceDescr
{
public:
// constructors
CFtdiDeviceDescr(void);
CFtdiDeviceDescr(uint32, uint32, const char *, const char *);
CFtdiDeviceDescr(const CFtdiDeviceDescr &);
// destructor
virtual ~CFtdiDeviceDescr() {}
// 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; }
// set
void SetUsed(bool used) { m_bUsed = used; }
protected:
// status
bool m_bUsed;
// data
uint32 m_uiVid;
uint32 m_uiPid;
char m_szDescription[FTDI_MAX_STRINGLENGTH];
char m_szSerial[FTDI_MAX_STRINGLENGTH];
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cftdidevicedescr_h */

91
ambed/cip.cpp Normal file
View File

@ -0,0 +1,91 @@
//
// cip.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cip.h"
#include <netdb.h>
////////////////////////////////////////////////////////////////////////////////////////
// constructors
CIp::CIp()
{
::memset(&m_Addr, 0, sizeof(m_Addr));
m_Addr.sin_family = AF_INET;
}
CIp::CIp(const char *sz)
{
::memset(&m_Addr, 0, sizeof(m_Addr));
m_Addr.sin_family = AF_INET;
// try xxx.xxx.xxx.xxxx first
m_Addr.sin_addr.s_addr = inet_addr(sz);
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
{
// otherwise try to resolve via dns
hostent *record = gethostbyname(sz);
if( record != NULL )
{
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
}
}
}
CIp::CIp(const struct sockaddr_in *sa)
{
::memcpy(&m_Addr, sa, sizeof(m_Addr));
}
CIp::CIp(const CIp &ip)
{
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
}
////////////////////////////////////////////////////////////////////////////////////////
// set
void CIp::SetSockAddr(struct sockaddr_in *sa)
{
::memcpy(&m_Addr, sa, sizeof(m_Addr));
}
////////////////////////////////////////////////////////////////////////////////////////
// operator
bool CIp::operator ==(const CIp &ip) const
{
return ( (ip.m_Addr.sin_family == m_Addr.sin_family) &&
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) &&
(ip.m_Addr.sin_port == m_Addr.sin_port)) ;
}
CIp::operator const char *() const
{
return ::inet_ntoa(m_Addr.sin_addr);
}

59
ambed/cip.h Normal file
View File

@ -0,0 +1,59 @@
//
// cip.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cip_h
#define cip_h
////////////////////////////////////////////////////////////////////////////////////////
// class
class CIp
{
public:
// constructors
CIp();
//CIp(uint8, uint8, uint8, uint8);
CIp(const struct sockaddr_in *);
CIp(const char *);
CIp(const CIp &);
// destructor
virtual ~CIp() {};
// sockaddr
void SetSockAddr(struct sockaddr_in *);
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
// operator
bool operator ==(const CIp &) const;
operator const char *() const;
protected:
// data
struct sockaddr_in m_Addr;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cip_h */

49
ambed/cpacket.cpp Normal file
View File

@ -0,0 +1,49 @@
//
// cpacket.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "cpacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructors
CPacket::CPacket()
{
m_iCh = 0;
m_uiPid = 0;
};
CPacket::CPacket(uint8 uiPid)
{
m_iCh = 0;
m_uiPid = uiPid;
}
CPacket::CPacket(const CPacket &packet)
{
m_iCh = packet.m_iCh;
m_uiPid = packet.m_uiPid;
};

58
ambed/cpacket.h Normal file
View File

@ -0,0 +1,58 @@
//
// cpacket.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cpacket_h
#define cpacket_h
////////////////////////////////////////////////////////////////////////////////////////
// class
class CPacket
{
public:
// constructors
CPacket();
CPacket(uint8);
CPacket(const CPacket &);
// destructor
virtual ~CPacket() {};
// get
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; }
protected:
// data
int m_iCh;
uint8 m_uiPid;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cpacket_h */

60
ambed/cpacketqueue.cpp Normal file
View File

@ -0,0 +1,60 @@
//
// cpacketqueue.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "cpacketqueue.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CPacketQueue::CPacketQueue()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CPacketQueue::~CPacketQueue()
{
// empty codec queue
while ( !empty() )
{
delete front();
pop();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// purge
void CPacketQueue::Purge(void)
{
// this assume queue is already locked
while ( !empty() )
{
delete front();
pop();
}
}

55
ambed/cpacketqueue.h Normal file
View File

@ -0,0 +1,55 @@
//
// cpacketqueue.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cpacketqueue_h
#define cpacketqueue_h
#include "cpacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CPacketQueue : public std::queue<CPacket *>
{
public:
// constructor
CPacketQueue();
// destructor
~CPacketQueue();
// lock
void Lock() { m_Mutex.lock(); }
void Unlock() { m_Mutex.unlock(); }
// purge
void Purge(void);
protected:
// status
std::mutex m_Mutex;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cpacketqueue_h */

241
ambed/cstream.cpp Normal file
View File

@ -0,0 +1,241 @@
//
// cstream.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "ctimepoint.h"
#include "cambeserver.h"
#include "cvocodecs.h"
#include "cambepacket.h"
#include "cstream.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
#define AMBE_FRAME_SIZE 9
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CStream::CStream()
{
m_uiId = 0;
m_uiPort = 0;
m_bStopThread = false;
m_pThread = NULL;
m_VocodecChannel = NULL;
m_LastActivity.Now();
m_iTotalPackets = 0;
m_iLostPackets = 0;
}
CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut)
{
m_uiId = uiId;
m_Callsign = Callsign;
m_Ip = Ip;
m_uiPort = 0;
m_uiCodecIn = uiCodecIn;
m_uiCodecOut = uiCodecOut;
m_bStopThread = false;
m_pThread = NULL;
m_VocodecChannel = NULL;
m_LastActivity.Now();
m_iTotalPackets = 0;
m_iLostPackets = 0;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CStream::~CStream()
{
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
g_Vocodecs.CloseChannel(m_VocodecChannel);
m_VocodecChannel = NULL;
}
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CStream::Init(uint16 uiPort)
{
bool ok;
// reset stop flag
m_bStopThread = false;
// create our socket
ok = m_Socket.Open(g_AmbeServer.GetListenIp(), uiPort);
if ( ok )
{
// open the vocodecchannel
ok &= ((m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut)) != NULL);
if ( ok )
{
// store port
m_uiPort = uiPort;
// start thread;
m_pThread = new std::thread(CStream::Thread, this);
// init timeout system
m_LastActivity.Now();
m_iTotalPackets = 0;
m_iLostPackets = 0;
}
else
{
std::cout << "Error opening stream : no suitable channel available" << std::endl;
}
}
else
{
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
}
// done
return ok;
}
void CStream::Close(void)
{
// close everything
m_Socket.Close();
if ( m_VocodecChannel != NULL )
{
m_VocodecChannel->Close();
}
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
// report
std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CStream::Thread(CStream *This)
{
while ( !This->m_bStopThread )
{
This->Task();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CStream::Task(void)
{
CBuffer Buffer;
static CIp Ip;
uint8 uiPid;
uint8 Ambe[AMBE_FRAME_SIZE];
CAmbePacket *packet;
CPacketQueue *queue;
// anything coming in from codec client ?
if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 )
{
// crack packet
if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) )
{
// transcode AMBE here
m_LastActivity.Now();
m_iTotalPackets++;
// post packet to VocoderChannel
packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe);
queue = m_VocodecChannel->GetPacketQueueIn();
queue->push(packet);
m_VocodecChannel->ReleasePacketQueueIn();
}
}
// anything in our queue ?
queue = m_VocodecChannel->GetPacketQueueOut();
while ( !queue->empty() )
{
// get the packet
packet = (CAmbePacket *)queue->front();
queue->pop();
// send it to client
EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe());
m_Socket.Send(Buffer, Ip, m_uiPort);
// and done
delete packet;
}
m_VocodecChannel->ReleasePacketQueueOut();
}
////////////////////////////////////////////////////////////////////////////////////////
// packet decoding helpers
bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe)
{
bool valid = false;
if ( Buffer.size() == 11 )
{
uint8 codec = Buffer.data()[0];
*pid = Buffer.data()[1];
::memcpy(ambe, &(Buffer.data()[2]), 9);
valid = (codec == GetCodecIn());
}
return valid;
}
////////////////////////////////////////////////////////////////////////////////////////
// packet encodeing helpers
void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe)
{
Buffer->clear();
Buffer->Append((uint8)GetCodecOut());
Buffer->Append((uint8)Pid);
Buffer->Append(Ambe, 9);
}

97
ambed/cstream.h Normal file
View File

@ -0,0 +1,97 @@
//
// cstream.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cstream_h
#define cstream_h
#include "cudpsocket.h"
#include "ccallsign.h"
#include "cvocodecchannel.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CStream
{
public:
// constructors
CStream();
CStream(uint16, const CCallsign &, const CIp &, uint8, uint8);
// destructor
virtual ~CStream();
// initialization
bool Init(uint16);
void Close(void);
// get
uint16 GetId(void) const { return m_uiId; }
uint16 GetPort(void) const { return m_uiPort; }
uint8 GetCodecIn(void) const { return m_uiCodecIn; }
uint8 GetCodecOut(void) const { return m_uiCodecOut; }
// activity timer
bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; }
// task
static void Thread(CStream *);
void Task(void);
protected:
// packet decoding helpers
bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *);
// packet encodeing helpers
void EncodeDvFramePacket(CBuffer *, uint8, uint8 *);
protected:
// data
uint16 m_uiId;
CUdpSocket m_Socket;
uint16 m_uiPort;
uint8 m_uiCodecIn;
uint8 m_uiCodecOut;
CVocodecChannel *m_VocodecChannel;
// client details
CCallsign m_Callsign;
CIp m_Ip;
// counters
int m_iTotalPackets;
int m_iLostPackets;
// activity timer
CTimePoint m_LastActivity;
// thread
bool m_bStopThread;
std::thread *m_pThread;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cstream_h */

53
ambed/ctimepoint.cpp Normal file
View File

@ -0,0 +1,53 @@
//
// ctimepoint.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CTimePoint::CTimePoint()
{
m_TimePoint = std::chrono::steady_clock::now();
}
////////////////////////////////////////////////////////////////////////////////////////
// operation
double CTimePoint::DurationSinceNow(void) const
{
std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now();
std::chrono::steady_clock::duration time_span = (Now - m_TimePoint);
return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den;
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CTimePoint::TaskSleepFor(uint ms)
{
std::chrono::milliseconds timespan(ms);
std::this_thread::sleep_for(timespan);
}

55
ambed/ctimepoint.h Normal file
View File

@ -0,0 +1,55 @@
//
// ctimepoint.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef ctimepoint_h
#define ctimepoint_h
////////////////////////////////////////////////////////////////////////////////////////
// class
class CTimePoint : public std::chrono::steady_clock::time_point
{
public:
// constructor
CTimePoint();
// destructor
virtual ~CTimePoint() {}
// operation
void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); }
double DurationSinceNow(void) const;
// task
static void TaskSleepFor(uint);
protected:
// data
std::chrono::steady_clock::time_point m_TimePoint;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* ctimepoint_h */

172
ambed/cudpsocket.cpp Normal file
View File

@ -0,0 +1,172 @@
//
// cudpsocket.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cudpsocket.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUdpSocket::CUdpSocket()
{
m_Socket = -1;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CUdpSocket::~CUdpSocket()
{
if ( m_Socket != -1 )
{
Close();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// open & close
bool CUdpSocket::Open(const CIp &ListenIp, uint16 uiPort)
{
bool open = false;
// create socket
m_Socket = socket(PF_INET,SOCK_DGRAM,0);
if ( m_Socket != -1 )
{
// initialize sockaddr struct
::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in));
m_SocketAddr.sin_family = AF_INET;
m_SocketAddr.sin_port = htons(uiPort);
m_SocketAddr.sin_addr.s_addr = inet_addr(ListenIp);
if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 )
{
fcntl(m_Socket, F_SETFL, O_NONBLOCK);
open = true;
}
else
{
close(m_Socket);
m_Socket = -1;
}
}
// done
return open;
}
void CUdpSocket::Close(void)
{
if ( m_Socket != -1 )
{
close(m_Socket);
m_Socket = -1;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// read
int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
{
struct sockaddr_in Sin;
fd_set FdSet;
unsigned int uiFromLen = sizeof(struct sockaddr_in);
int iRecvLen = -1;
struct timeval tv;
// socket valid ?
if ( m_Socket != -1 )
{
// control socket
FD_ZERO(&FdSet);
FD_SET(m_Socket, &FdSet);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
select(m_Socket + 1, &FdSet, 0, 0, &tv);
// allocate buffer
Buffer->resize(UDP_BUFFER_LENMAX);
// read
iRecvLen = (int)recvfrom(m_Socket,
(void *)Buffer->data(), UDP_BUFFER_LENMAX,
0, (struct sockaddr *)&Sin, &uiFromLen);
// handle
if ( iRecvLen != -1 )
{
// adjust buffer size
Buffer->resize(iRecvLen);
// get IP
Ip->SetSockAddr(&Sin);
}
}
// done
return iRecvLen;
}
////////////////////////////////////////////////////////////////////////////////////////
// write
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip)
{
CIp temp(Ip);
return (int)::sendto(m_Socket,
(void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
int CUdpSocket::Send(const char *Buffer, const CIp &Ip)
{
CIp temp(Ip);
return (int)::sendto(m_Socket,
(void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport)
{
CIp temp(Ip);
temp.GetSockAddr()->sin_port = htons(destport);
return (int)::sendto(m_Socket,
(void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport)
{
CIp temp(Ip);
temp.GetSockAddr()->sin_port = htons(destport);
return (int)::sendto(m_Socket,
(void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}

78
ambed/cudpsocket.h Normal file
View File

@ -0,0 +1,78 @@
//
// cudpsocket.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cudpsocket_h
#define cudpsocket_h
#include <sys/types.h>
//#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include "cip.h"
#include "cbuffer.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
#define UDP_BUFFER_LENMAX 1024
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUdpSocket
{
public:
// constructor
CUdpSocket();
// destructor
~CUdpSocket();
// open & close
bool Open(const CIp &, uint16);
void Close(void);
int GetSocket(void) { return m_Socket; }
// read
int Receive(CBuffer *, CIp *, int);
// write
int Send(const CBuffer &, const CIp &);
int Send(const CBuffer &, const CIp &, uint16);
int Send(const char *, const CIp &);
int Send(const char *, const CIp &, uint16);
protected:
// data
int m_Socket;
struct sockaddr_in m_SocketAddr;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cudpsocket_h */

185
ambed/cusb3003interface.cpp Normal file
View File

@ -0,0 +1,185 @@
//
// cusb3003interface.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cambepacket.h"
#include "cusb3003interface.h"
#include "cvocodecs.h"
////////////////////////////////////////////////////////////////////////////////////////
// configuration:
//
// PKT_CHANNEL0 = DSTAR (AMBEPLUS)
// PKT_CHANNEL1 = DMR/C4FM (AMBE2PLUS)
// PKT_CHANNEL2 = UNUSED or HYBRID
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial)
{
m_uiChCodecs[0]= CODEC_AMBEPLUS;
m_uiChCodecs[1]= CODEC_AMBE2PLUS;
m_uiChCodecs[2]= CODEC_NONE;
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CUsb3003Interface::Init(uint8 uiOddCodec)
{
bool ok = true;
// init the odd channel
m_uiChCodecs[2] = uiOddCodec;
// base class
ok &= CUsb3xxxInterface::Init();
// do not create our channels now
// this is delegated to caller (CVocodecs) as our channel
// may be hybrids between 2 interfaces in case of odd n' of channel device)
// done
return ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// manage Channels
uint8 CUsb3003Interface::GetChannelCodec(int iCh) const
{
uint8 uiCodec = CODEC_NONE;
if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) )
{
uiCodec = m_uiChCodecs[iCh];
}
return uiCodec;
}
////////////////////////////////////////////////////////////////////////////////////////
// manage vocodec channels
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh)
{
CVocodecChannel *Channel = NULL;
bool done = false;
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
{
if ( iCh == 2 )
{
if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) )
{
Channel = m_Channels[i];
done = true;
}
}
else
{
if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
{
Channel = m_Channels[i];
done = true;
}
}
}
return Channel;
}
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh)
{
CVocodecChannel *Channel = NULL;
bool done = false;
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
{
if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
{
Channel = m_Channels[i];
done = true;
}
}
return Channel;
}
////////////////////////////////////////////////////////////////////////////////////////
// low level
bool CUsb3003Interface::SoftResetDevice(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-3xxx soft reset failed" << std::endl;
}
// done
return ok;
}
bool CUsb3003Interface::ConfigureDevice(void)
{
bool ok = true;
uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 };
uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 };
// configure each channels for desired codec
for ( int i = 0; i < USB3003_NB_CH; i++ )
{
switch ( m_uiChCodecs[i] )
{
case CODEC_AMBEPLUS:
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0);
break;
case CODEC_AMBE2PLUS:
//ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, -12, 0); // DSTAR->DMR ok
//ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, +10); // DMR->DSTAR ok
//ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, -12, +10); // not ok!
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0);
break;
case CODEC_NONE:
default:
break;
}
}
// done
return ok;
}

70
ambed/cusb3003interface.h Normal file
View File

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

667
ambed/cusb3xxxinterface.cpp Normal file
View File

@ -0,0 +1,667 @@
//
// cusb3xxxinterface.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "ctimepoint.h"
#include "cusb3xxxinterface.h"
#include "cvocodecchannel.h"
#include "cambeserver.h"
// queues ID
#define QUEUE_CHANNEL 0
#define QUEUE_SPEECH 1
////////////////////////////////////////////////////////////////////////////////////////
// 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);
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CUsb3xxxInterface::~CUsb3xxxInterface()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CUsb3xxxInterface::Init(void)
{
bool ok = true;
// open USB device
std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl;
if ( ok &= OpenDevice() )
{
// reset
//std::cout << "Reseting " << m_szDeviceName << "device" << std::endl;
if ( ok &= SoftResetDevice() )
{
// read version
//std::cout << "Reading " << m_szDeviceName << " device version" << std::endl;
if ( ok &= ReadDeviceVersion() )
{
// send configuration packet(s)
//std::cout << "Configuring " << m_szDeviceName << " device" << std::endl;
ok &= DisableParity();
ok &= ConfigureDevice();
}
}
}
std::cout << std::endl;
// base class
if ( ok )
{
ok &= CVocodecInterface::Init();
}
// done
return ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CUsb3xxxInterface::Task(void)
{
CBuffer Buffer;
int iCh;
CPacketQueue *Queue;
CVocodecChannel *Channel;
CAmbePacket AmbePacket;
CVoicePacket VoicePacket;
bool done;
// TODO :
// preserve packets PIDs, so the transcoded CAmbePacket returned
// to CStream client is garantied to have the same PID
// than the corresponding incoming packet
// process the device incoming packet
// get all packets from device and push them
// to the relevant clients queues
if ( ReadBuffer(&Buffer) )
{
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);
// push back to relevant channel voice queue
// our incoming channel packet has now been through the decoder
// find the coupled channel encoder and push to it's queue
// this is were the DVSI enc-dec channel crossover take place
Channel = GetChannelWithChannelIn(iCh);
if ( Channel != NULL )
{
Queue = Channel->GetVoiceQueue();
CVoicePacket *clone = new CVoicePacket(VoicePacket);
clone->ApplyGain(Channel->GetSpeechGain());
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);
// push back to relevant channel outcoming queue
Channel = GetChannelWithChannelOut(iCh);
if ( Channel != NULL )
{
Queue = Channel->GetPacketQueueOut();
CAmbePacket *clone = new CAmbePacket(AmbePacket);
Queue->push(clone);
Channel->ReleasePacketQueueOut();
}
}
}
// process the streams (channels) incoming queue
// make sure that packets from different channels
// are interlaced so to keep the device fifo busy
do
{
done = true;
for ( int i = 0; i < m_Channels.size(); i++)
{
// get channel
Channel = m_Channels[i];
// any packet in voice queue ?
if ( Channel->IsInterfaceOut(this) )
{
Queue = Channel->GetVoiceQueue();
if ( !Queue->empty() )
{
// get packet
CVoicePacket *Packet = (CVoicePacket *)Queue->front();
Queue->pop();
// post it to relevant channel encoder
Packet->SetChannel(Channel->GetChannelOut());
m_SpeechQueue.push(Packet);
// done
done = false;
}
Channel->ReleaseVoiceQueue();
}
// any packet in ambe queue for us ?
if ( Channel->IsInterfaceIn(this) )
{
Queue = Channel->GetPacketQueueIn();
if ( !Queue->empty() )
{
// get packet
CAmbePacket *Packet = (CAmbePacket *)Queue->front();
Queue->pop();
// post it to relevant channel decoder
Packet->SetChannel(Channel->GetChannelIn());
m_ChannelQueue.push(Packet);
// done
done = false;
}
Channel->ReleasePacketQueueIn();
}
}
} while (!done);
// process device incoming queues
// 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) )
{
if ( m_iActiveQueue == QUEUE_CHANNEL )
{
// post next channel packet
if ( !m_ChannelQueue.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;
}
else
{
// post next speech packet
if ( !m_SpeechQueue.empty() )
{
// 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
#ifdef DEBUG_DUMPFILE
g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush();
#endif
delete Packet;
}
// and interlace
m_iActiveQueue = QUEUE_CHANNEL;
}
}
// and wait a bit
CTimePoint::TaskSleepFor(2);
}
////////////////////////////////////////////////////////////////////////////////////////
// decoder helper
bool CUsb3xxxInterface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet)
{
bool valid = false;
uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL };
if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0))
{
*ch = buffer.data()[4] - PKT_CHANNEL0;
if ( *ch == 0 )
packet->SetCodec(CODEC_AMBEPLUS);
else if ( *ch == 1 )
packet->SetCodec(CODEC_AMBE2PLUS);
else
packet->SetCodec(CODEC_NONE);
packet->SetAmbe(&(buffer.data()[7]));
valid = (*ch < GetNbChannels());
//std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl;
}
return valid;
}
bool CUsb3xxxInterface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet)
{
bool valid = false;
if ( (buffer.size() > 6) &&
(buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) &&
(buffer.data()[5] == PKT_SPEECHD) )
{
*ch = buffer.data()[4] - PKT_CHANNEL0;
packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2);
valid = (*ch < GetNbChannels());
//std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl;
}
return valid;
}
////////////////////////////////////////////////////////////////////////////////////////
// encoder helpers
void CUsb3xxxInterface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet)
{
uint size = (uint16)packet->GetAmbeSize() + 3;
buffer->clear();
buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_CHANNEL);
buffer->Append((uint8)(PKT_CHANNEL0+ch));
buffer->Append((uint8)(PKT_CHAND));
buffer->Append((uint8)(packet->GetAmbeSize()*8));
buffer->Append(packet->GetAmbe(), packet->GetAmbeSize());
}
void CUsb3xxxInterface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet)
{
uint16 size = (uint16)packet->GetVoiceSize() + 3;
buffer->clear();
buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_SPEECH);
buffer->Append((uint8)(PKT_CHANNEL0+ch));
buffer->Append((uint8)PKT_SPEECHD);
buffer->Append((uint8)(packet->GetVoiceSize()/2));
buffer->Append(packet->GetVoice(), packet->GetVoiceSize());
}
////////////////////////////////////////////////////////////////////////////////////////
// low level
bool CUsb3xxxInterface::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);
ftStatus = FT_OpenEx((PVOID)m_szDeviceName, FT_OPEN_BY_DESCRIPTION, &m_FtdiHandle);
baudrate = 921600;
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 usb-3012 pull DTR high to take AMBE3003 out of reset.
//for other devices noting is connected to DTR so it is a dont care
ftStatus = FT_ClrDtr(m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", 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 CUsb3xxxInterface::ReadDeviceVersion(void)
{
bool ok = false;
int i, len;
char rxpacket[128];
char txpacket[8] =
{
PKT_HEADER,
0,
4,
PKT_CONTROL,
PKT_PRODID,
PKT_VERSTRING,
PKT_PARITYBYTE,
4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE
};
// 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);
//we succeed in reading a packet, print it out
std::cout << "ReadDeviceVersion : ";
for ( i = 4; i < len+4 ; i++ )
{
std::cout << (char)(rxpacket[i] & 0x00ff);
}
std::cout << std::endl;
}
return ok;
}
bool CUsb3xxxInterface::DisableParity(void)
{
bool ok = false;
int len;
char rxpacket[16];
char txpacket[8] =
{
PKT_HEADER,
0,
4,
PKT_CONTROL,
PKT_PARITYMODE,0x00,
PKT_PARITYBYTE,
4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE
};
// 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 == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) );
}
return ok;
}
bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain)
{
bool ok = false;
int len;
char rxpacket[64];
char txpacket[] =
{
PKT_HEADER,
0,
33,
PKT_CONTROL,
0x00,
PKT_ECMODE, 0x00,0x00,
PKT_DCMODE, 0x00,0x00,
PKT_COMPAND,0x00,
PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
PKT_CHANFMT,0x00,0x00,
PKT_SPCHFMT,0x00,0x00,
PKT_GAIN, 0x00,0x00,
PKT_INIT, 0x03
};
// update packet content
txpacket[4] = pkt_ch;
:: memcpy(&(txpacket[14]), pkt_ratep, 12);
txpacket[33] = (uint8)(signed char)in_gain;
txpacket[34] = (uint8)(signed char)out_gain;
// 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 == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) );
}
return ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// io level
bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer)
{
bool ok = false;
int n;
// any byte in tx queue ?
if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK )
{
//if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) )
if ( n != 0 )
{
buffer->clear();
buffer->resize(USB3XXX_MAXPACKETSIZE);
n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE);
buffer->resize(n);
ok = (n != 0);
}
}
return ok;
}
bool CUsb3xxxInterface::WriteBuffer(const CBuffer &buffer)
{
return FTDI_write_packet(m_FtdiHandle, (const char *)buffer.data(), (int)buffer.size());
}
int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen)
{
int plen;
// first read 4 bytes header
if ( FTDI_read_bytes(ftHandle, pkt, 4) )
{
// get payload length
plen = (pkt[1] & 0x00ff);
plen <<= 8;
plen += (pkt[2] & 0x00ff);
// check buffer length
if (plen+4 > maxlen)
{
std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl;
FT_Purge(ftHandle, FT_PURGE_RX);
return 0;
}
// and get payload
if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) )
{
return plen+4;
}
}
return 0;
}
bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len)
{
// this relies on FT_SetTimouts() mechanism
int n;
bool ok = false;
ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len);
if ( !ok )
{
//FT_Purge(ftHandle, FT_PURGE_RX);
std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl;
}
return ok;
}
/*
int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen)
{
FT_STATUS ftStatus;
int nr;
int plen;
int offset = 0;
int nrt;
int len;
// first read 4 bytes header
len = 4;
nrt = 0;
offset = 0;
do
{
ftStatus = FT_Read( ftHandle, (LPVOID)&pkt[offset], len, (LPDWORD)&nr );
if (ftStatus != FT_OK)
{
FTDI_Error((char *)"FT_Read C0", ftStatus );
return 0;
}
len -= nr;
nrt += nr;
offset += nr;
} while (len > 0);
if (nrt != 4)
{
std::cout << "FTDI_read_packet nrt = " << nrt << std::endl;
return 0;
}
// get packet payload length
plen = (pkt[1] & 0x00ff);
plen <<= 8;
plen += (pkt[2] & 0x00ff);
if (plen+4 > maxlen)
{
std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl;
plen = maxlen-4;
}
// and read payload
len = plen;
nrt = 0;
offset = 4;
do
{
ftStatus = FT_Read( ftHandle, (LPVOID)&pkt[offset], len, (LPDWORD)&nr );
if (ftStatus != FT_OK)
{
FTDI_Error((char *)"FT_Read C1", ftStatus );
return 0;
}
len -= nr;
nrt += nr;
offset += nr;
} while (len > 0);
if (nrt != plen)
{
std::cout << "FTDI_read_packet nrt = " << nrt << " plen = " << plen << std::endl;
//printf("reading packet nrt=%d plen=%d\n", nrt, plen );
//printf("pkt[0]=0x%02x\n", pkt[0] & 0x00ff );
//printf("pkt[1]=0x%02x\n", pkt[1] & 0x00ff );
//printf("pkt[2]=0x%02x\n", pkt[2] & 0x00ff );
//printf("pkt[3]=0x%02x\n", pkt[3] & 0x00ff );
//printf("pkt[4]=0x%02x\n", pkt[4] & 0x00ff );
//printf("pkt[5]=0x%02x\n", pkt[5] & 0x00ff );
return 0;
}
//NOTE: we could extract the channel data from the packet, but for this
//simple example, the whole packet is echoed back for decoding so
//we don't bother extracting the channel data
return plen+4;
}
*/
bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len)
{
FT_STATUS ftStatus;
bool ok = true;
int nwritten;
if ( len > 0 )
{
ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten);
ok = (ftStatus == FT_OK) && (len == nwritten);
if ( !ok )
{
FTDI_Error((char *)"FT_Write", ftStatus);
}
}
return ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// error reporting
void CUsb3xxxInterface::FTDI_Error(char *func_string, FT_STATUS ftStatus)
{
std::cout << "FTDI function " << func_string << " error " << (int)ftStatus << std::endl;
}

134
ambed/cusb3xxxinterface.h Normal file
View File

@ -0,0 +1,134 @@
//
// cusb3xxxinterface.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cusb3xxxinterface_h
#define cusb3xxxinterface_h
#include "ftd2xx.h"
#include "cftdidevicedescr.h"
#include "cbuffer.h"
#include "cambepacket.h"
#include "cvoicepacket.h"
#include "cvocodecinterface.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
#define USB3XXX_MAXPACKETSIZE 1024 // must be multiple of 64
#define PKT_HEADER 0x61
#define PKT_CONTROL 0x00
#define PKT_CHANNEL 0x01
#define PKT_SPEECH 0x02
#define PKT_SPEECHD 0x00
#define PKT_CHAND 0x01
#define PKT_RATET 0x09
#define PKT_INIT 0x0b
#define PKT_PRODID 0x30
#define PKT_VERSTRING 0x31
#define PKT_PARITYBYTE 0x2F
#define PKT_RESET 0x33
#define PKT_READY 0x39
#define PKT_CHANNEL0 0x40
#define PKT_CHANNEL1 0x41
#define PKT_CHANNEL2 0x42
#define PKT_PARITYMODE 0x3F
#define PKT_ECMODE 0x05
#define PKT_DCMODE 0x06
#define PKT_COMPAND 0x32
#define PKT_RATEP 0x0A
#define PKT_CHANFMT 0x15
#define PKT_SPCHFMT 0x16
#define PKT_GAIN 0x4B
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUsb3xxxInterface : public CVocodecInterface
{
public:
// constructors
CUsb3xxxInterface(uint32, uint32, const char *, const char *);
// destructor
virtual ~CUsb3xxxInterface();
// initialization
bool Init(void);
// get
const char *GetName(void) const { return m_szDeviceName; }
const char *GetSerial(void) const { return m_szDeviceSerial; }
// task
void Task(void);
protected:
// decoder helper
bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *);
bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *);
// encoder helpers
void EncodeChannelPacket(CBuffer *, int, CAmbePacket *);
void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *);
// low level
bool OpenDevice(void);
virtual bool SoftResetDevice(void) { return false; }
bool ReadDeviceVersion(void);
bool DisableParity(void);
virtual bool ConfigureDevice(void) { return false; }
bool ConfigureChannel(uint8, const uint8 *, int, int);
// io level
bool ReadBuffer(CBuffer *);
bool WriteBuffer(const CBuffer &);
int FTDI_read_packet(FT_HANDLE, char *, int);
bool FTDI_read_bytes(FT_HANDLE, char *, int);
bool FTDI_write_packet(FT_HANDLE, const char *, int);
// error reporting
void FTDI_Error(char *, FT_STATUS);
protected:
// data
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;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cusb3xxxinterface_h */

109
ambed/cvocodecchannel.cpp Normal file
View File

@ -0,0 +1,109 @@
//
// cvocodecchannel.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cvocodecchannel.h"
#include "cvocodecinterface.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain)
{
m_bOpen = false;
m_InterfaceIn = InterfaceIn;
m_iChannelIn = iChIn;
m_InterfaceOut = InterfaceOut;
m_iChannelOut = iChOut;
m_iSpeechGain = iSpeechGain;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CVocodecChannel::~CVocodecChannel()
{
PurgeAllQueues();
}
////////////////////////////////////////////////////////////////////////////////////////
// open & close
bool CVocodecChannel::Open(void)
{
bool ok = false;
if ( !m_bOpen )
{
m_bOpen = true;
ok = true;
PurgeAllQueues();
std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl;
}
return ok;
}
void CVocodecChannel::Close(void)
{
if ( m_bOpen )
{
m_bOpen = false;
PurgeAllQueues();
std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// get
uint8 CVocodecChannel::GetCodecIn(void) const
{
return m_InterfaceIn->GetChannelCodec(m_iChannelIn);
}
uint8 CVocodecChannel::GetCodecOut(void) const
{
return m_InterfaceOut->GetChannelCodec(m_iChannelOut);
}
////////////////////////////////////////////////////////////////////////////////////////
// queues helpers
void CVocodecChannel::PurgeAllQueues(void)
{
GetPacketQueueIn()->Purge();
ReleasePacketQueueIn();
GetPacketQueueOut()->Purge();
ReleasePacketQueueOut();
GetVoiceQueue()->Purge();
ReleaseVoiceQueue();
}

98
ambed/cvocodecchannel.h Normal file
View File

@ -0,0 +1,98 @@
//
// cvocodecchannel.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cvocodecchannel_h
#define cvocodecchannel_h
#include "cpacketqueue.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CVocodecInterface;
class CVocodecChannel
{
public:
// constructors
CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int);
// destructor
virtual ~CVocodecChannel();
// open & close
bool Open(void);
bool IsOpen(void) const { return m_bOpen; }
void Close(void);
// get
uint8 GetCodecIn(void) const;
uint8 GetCodecOut(void) const;
int GetChannelIn(void) const { return m_iChannelIn; }
int GetChannelOut(void) const { return m_iChannelOut; }
int GetSpeechGain(void) const { return m_iSpeechGain; }
// interfaces
bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); }
bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); }
// queues
CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; }
void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); }
CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; }
void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); }
CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; }
void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); }
// operators
//virtual bool operator ==(const CVocodecChannel &) const { return false; }
protected:
// queues helpers
void PurgeAllQueues(void);
protected:
// status
bool m_bOpen;
// connected interfaces
CVocodecInterface *m_InterfaceIn;
int m_iChannelIn;
CVocodecInterface *m_InterfaceOut;
int m_iChannelOut;
// ambe queues
CPacketQueue m_QueuePacketIn;
CPacketQueue m_QueuePacketOut;
// voice queue
CPacketQueue m_QueueVoice;
// settings
int m_iSpeechGain;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cvocodecchannel_h */

View File

@ -0,0 +1,95 @@
//
// cvocodecinterface.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cpacketqueue.h"
#include "cvocodecinterface.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CVocodecInterface::CVocodecInterface()
{
m_Channels.reserve(5);
m_bStopThread = false;
m_pThread = NULL;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CVocodecInterface::~CVocodecInterface()
{
// empty channel array
// chennels are deleted by their owner (CVocodecs)
m_Channels.clear();
// stop thread
m_bStopThread = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CVocodecInterface::Init(void)
{
// reset stop flag
m_bStopThread = false;
// start thread;
m_pThread = new std::thread(CVocodecInterface::Thread, this);
// done
return true;
}
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CVocodecInterface::Thread(CVocodecInterface *This)
{
while ( !This->m_bStopThread )
{
This->Task();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// manage Channels
void CVocodecInterface::AddChannel(CVocodecChannel *Channel)
{
m_Channels.push_back(Channel);
}

75
ambed/cvocodecinterface.h Normal file
View File

@ -0,0 +1,75 @@
//
// cvocodecinterface.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cvocodecinterface_h
#define cvocodecinterface_h
#include "cvocodecchannel.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CVocodecs;
class CVocodecInterface
{
public:
// constructors
CVocodecInterface();
// destructor
virtual ~CVocodecInterface();
// initialization
virtual bool Init(void);
// get
virtual const char *GetName(void) const { return ""; }
// manage channels
virtual int GetNbChannels(void) const { return 0; }
virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; }
void AddChannel(CVocodecChannel *);
virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; }
virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; }
// task
static void Thread(CVocodecInterface *);
virtual void Task(void) {};
// operators
virtual bool operator ==(const CVocodecInterface &) const { return false; }
protected:
// array of channels
std::vector<CVocodecChannel *> m_Channels;
// thread
bool m_bStopThread;
std::thread *m_pThread;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cvocodecinterface_h */

399
ambed/cvocodecs.cpp Normal file
View File

@ -0,0 +1,399 @@
//
// cvocodecs.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "cusb3003interface.h"
#include "cvocodecs.h"
////////////////////////////////////////////////////////////////////////////////////////
// global object
CVocodecs g_Vocodecs;
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CVocodecs::CVocodecs()
{
m_Interfaces.reserve(5);
m_Channels.reserve(20);
m_FtdiDeviceDescrs.reserve(10);
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CVocodecs::~CVocodecs()
{
// delete channels
m_MutexChannels.lock();
{
for ( int i = 0; i < m_Channels.size(); i++ )
{
delete m_Channels[i];
}
m_Channels.clear();
}
m_MutexChannels.unlock();
// delete interfaces
m_MutexInterfaces.lock();
{
for ( int i = 0; i < m_Interfaces.size(); i++ )
{
delete m_Interfaces[i];
}
m_Interfaces.clear();
}
m_MutexInterfaces.unlock();
// delete ftdi device descriptors
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
delete m_FtdiDeviceDescrs[i];
}
}
////////////////////////////////////////////////////////////////////////////////////////
// initialization
bool CVocodecs::Init(void)
{
bool ok = true;
int iNbCh = 0;
// discover and add vocodecs interfaces
DiscoverFtdiDevices();
// and create interfaces for the discovered devices
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
// create relevant interface
if ( m_FtdiDeviceDescrs[i]->IsUsb3012() )
{
iNbCh += InitUsb3012(*m_FtdiDeviceDescrs[i]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
}
else if ( m_FtdiDeviceDescrs[i]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed() )
{
// another unsed USB-3003 avaliable for a pair ?
bool found = false;
int j = i+1;
while ( !found && (j < m_FtdiDeviceDescrs.size()) &&
!(m_FtdiDeviceDescrs[j]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed()) )
{
j++;
}
// pair ?
if ( found )
{
// yes!
iNbCh += InitUsb3003Pair(*m_FtdiDeviceDescrs[i], *m_FtdiDeviceDescrs[j]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
m_FtdiDeviceDescrs[j]->SetUsed(true);
}
else
{
// just single
iNbCh += InitUsb3003(*m_FtdiDeviceDescrs[i]);
m_FtdiDeviceDescrs[i]->SetUsed(true);
}
}
}
if ( ok )
{
std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels availables" << std::endl;
}
else
{
std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl;
}
// done
return ok;
}
////////////////////////////////////////////////////////////////////////////////////////
// initialisation helpers
bool CVocodecs::DiscoverFtdiDevices(void)
{
bool ok = false;
int iNbDevices = 0;
FT_DEVICE_LIST_INFO_NODE *list;
// clear vector
for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{
delete m_FtdiDeviceDescrs[i];
}
// and discover
if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK )
{
std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl;
ok = true;
if ( iNbDevices > 0 )
{
// allocate the list
list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices];
// fill
if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK )
{
// process
for ( int i = 0; i < iNbDevices; i++ )
{
std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl;
CFtdiDeviceDescr *descr = new CFtdiDeviceDescr(
LOWORD(list[i].ID), HIWORD(list[i].ID),
list[i].Description, list[i].SerialNumber);
m_FtdiDeviceDescrs.push_back(descr);
}
}
else
{
ok = false;
}
// and delete
delete list;
}
}
// done
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;
}
////////////////////////////////////////////////////////////////////////////////////////
// manage channels
CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut)
{
CVocodecChannel *Channel = NULL;
bool done = false;
// loop on all interface until suitable & available channel found
m_MutexChannels.lock();
for ( int i = 0; (i < m_Channels.size()) && !done; i++ )
{
if ( !m_Channels[i]->IsOpen() &&
(m_Channels[i]->GetCodecIn() == uiCodecIn) &&
(m_Channels[i]->GetCodecOut() == uiCodecOut) )
{
if ( m_Channels[i]->Open() )
{
Channel = m_Channels[i];
done = true;
}
}
}
m_MutexChannels.unlock();
// done
return Channel;
}
void CVocodecs::CloseChannel(CVocodecChannel *Channel)
{
Channel->Close();
}

78
ambed/cvocodecs.h Normal file
View File

@ -0,0 +1,78 @@
//
// cvocodecs.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cvocodecs_h
#define cvocodecs_h
#include "cftdidevicedescr.h"
#include "cvocodecinterface.h"
#include "cvocodecchannel.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CVocodecs
{
public:
// constructors
CVocodecs();
// destructor
virtual ~CVocodecs();
// initialization
bool Init(void);
// manage interfaces
int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); }
CVocodecInterface *GetInterface(int);
// manage channels
CVocodecChannel *OpenChannel(uint8, uint8);
void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); }
void CloseChannel(CVocodecChannel *);
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 &);
protected:
// array of interfaces
std::mutex m_MutexInterfaces;
std::vector<CVocodecInterface *> m_Interfaces;
// array of channels
std::mutex m_MutexChannels;
std::vector<CVocodecChannel *> m_Channels;
// array of FTDI desciptors
std::vector<CFtdiDeviceDescr *> m_FtdiDeviceDescrs;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cvocodecs_h */

86
ambed/cvoicepacket.cpp Normal file
View File

@ -0,0 +1,86 @@
//
// cvoicepacket.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include <math.h>
#include "cvoicepacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CVoicePacket::CVoicePacket()
{
m_iSize = 0;
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
}
CVoicePacket::CVoicePacket(const uint8 *voice, int size)
{
m_iSize = MIN(size, sizeof(m_uiVoice));
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
::memcpy(m_uiVoice, voice, m_iSize);
}
CVoicePacket::CVoicePacket(const CVoicePacket &packet)
: CPacket(packet)
{
m_iSize = packet.m_iSize;
::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice));
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CVoicePacket::~CVoicePacket()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// Set
void CVoicePacket::SetVoice(const uint8 *voice, int size)
{
m_iSize = MIN(size, sizeof(m_uiVoice));
::memset(m_uiVoice, 0, sizeof(m_uiVoice));
::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);
}
}

68
ambed/cvoicepacket.h Normal file
View File

@ -0,0 +1,68 @@
//
// cvoicepacket.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cvoicepacket_h
#define cvoicepacket_h
#include "cpacket.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
// frame sizes
#define VOICE_SIZEMAX 512
////////////////////////////////////////////////////////////////////////////////////////
// class
class CVoicePacket : public CPacket
{
public:
// constructors
CVoicePacket();
CVoicePacket(const uint8 *, int);
CVoicePacket(const CVoicePacket &);
// destructor
virtual ~CVoicePacket();
// get
uint8 *GetVoice(void) { return m_uiVoice; }
int GetVoiceSize(void) const { return m_iSize; }
// set
void SetVoice(const uint8 *, int);
// gain
void ApplyGain(int);
protected:
// data
int m_iSize;
uint8 m_uiVoice[VOICE_SIZEMAX];
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cvoicepacket_h */

1443
ambed/ftd2xx.h Executable file

File diff suppressed because it is too large Load Diff

127
ambed/main.cpp Normal file
View File

@ -0,0 +1,127 @@
//
// main.cpp
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include "ctimepoint.h"
#include "cambeserver.h"
#include "syslog.h"
#include <sys/stat.h>
////////////////////////////////////////////////////////////////////////////////////////
// global objects
////////////////////////////////////////////////////////////////////////////////////////
// function declaration
int main(int argc, const char * argv[])
{
#ifdef RUN_AS_DAEMON
// redirect cout, cerr and clog to syslog
syslog::redirect cout_redir(std::cout);
syslog::redirect cerr_redir(std::cerr);
syslog::redirect clog_redir(std::clog);
//Fork the Parent Process
pid_t pid, sid;
pid = ::fork();
//pid = ::vfork();
if ( pid < 0 )
{
exit(EXIT_FAILURE);
}
// We got a good pid, Close the Parent Process
if (pid > 0)
{
exit(EXIT_SUCCESS);
}
// Change File Mask
::umask(0);
//Create a new Signature Id for our child
sid = ::setsid();
if (sid < 0)
{
exit(EXIT_FAILURE);
}
// Change Directory
// If we cant find the directory we exit with failure.
if ( (::chdir("/")) < 0)
{
exit(EXIT_FAILURE);
}
// Close Standard File Descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
#endif
// check arguments
if ( argc != 2 )
{
std::cout << "Usage: ambed ip" << std::endl;
std::cout << "example: ambed 192.168.178.212" << std::endl;
return 1;
}
// initialize ambeserver
g_AmbeServer.SetListenIp(CIp(argv[1]));
// and let it run
std::cout << "Starting AMBEd" << std::endl << std::endl;
if ( !g_AmbeServer.Start() )
{
std::cout << "Error starting AMBEd" << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl;
#ifdef RUN_AS_DAEMON
// run forever
while ( true )
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
}
#else
// wait any key
for (;;);
//std::cin.get();
#endif
// and wait for end
g_AmbeServer.Stop();
std::cout << "AMBEd stopped" << std::endl;
// done
exit(EXIT_SUCCESS);
}

110
ambed/main.h Normal file
View File

@ -0,0 +1,110 @@
//
// main.h
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef main_h
#define main_h
#include <vector>
#include <array>
#include <map>
#include <queue>
#include <chrono>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <ctime>
#include <cctype>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <arpa/inet.h>
////////////////////////////////////////////////////////////////////////////////////////
// defines
// version -----------------------------------------------------
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_REVISION 0
// global ------------------------------------------------------
//#define RUN_AS_DAEMON
#define NB_MAX_STREAMS 99
//#define DEBUG_DUMPFILE
// 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
#define CODEC_AMBEPLUS 1
#define CODEC_AMBE2PLUS 2
// Transcoding speech gains
#define CODECGAIN_AMBEPLUS -10 // in dB
#define CODECGAIN_AMBE2PLUS +10 // in dB
// Timeouts -----------------------------------------------------
#define STREAM_ACTIVITY_TIMEOUT 3 // in seconds
////////////////////////////////////////////////////////////////////////////////////////
// typedefs
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned int uint;
////////////////////////////////////////////////////////////////////////////////////////
// macros
#define MIN(a,b) ((a) < (b))?(a):(b)
#define MAX(a,b) ((a) > (b))?(a):(b)
#define MAKEWORD(low, high) ((uint16)(((uint8)(low)) | (((uint16)((uint8)(high))) << 8)))
#define MAKEDWORD(low, high) ((uint32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16)))
#define LOBYTE(w) ((uint8)(uint16)(w & 0x00FF))
#define HIBYTE(w) ((uint8)((((uint16)(w)) >> 8) & 0xFF))
#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF))
#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF))
////////////////////////////////////////////////////////////////////////////////////////
// global objects
class CAmbeServer;
extern CAmbeServer g_AmbeServer;
class CVocodecs;
extern CVocodecs g_Vocodecs;
////////////////////////////////////////////////////////////////////////////////////////
#endif /* main_h */

22
ambed/makefile Normal file
View File

@ -0,0 +1,22 @@
CC=g++
CFLAGS=-c -std=c++11 -pthread
LDFLAGS=-std=c++11 -pthread
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=ambed
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
clean:
$(RM) *.o
install:
mkdir -p /ambed
cp ./ambed /ambed/
cp ./run /ambed/

103
ambed/readme Normal file
View File

@ -0,0 +1,103 @@
//
// readme
// ambed
//
// Created by Jean-Luc Deltombe (LX3JL) on 09/07/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of ambed.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
Hardware compatibility.
======================
This version of ambed is compatible with FTDI's USB-3003 and USB-3012 device
Available transcoding channels:
device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels
----------------------------------------------------------------------
USB-3003 1 1 1
USB-3012 4 4 4
multiple USB-3xxx can be used at the same time.
Instructions:
=============
1) Installation of FTDI drivers
Download from FTDI web site the latest D2XX driver package (tested on 1.4.6).
Follow FTDI provided documentation for installation and testing of the drivers.
2) installation of g++ compiler
# apt-get install build-essential
# apt-get install g++-4.7
2) download and compile ambed
# git clone https://github.com/LX3JL/xlxd.git
# cd xlxd/ambed/
# make
# make clean
# make install
3) configuring ambed startup script
# nano /ambed/run
edit following line to match your IP:
sudo /ambed/ambed 127.0.0.1 &
if ambed is running on same machine than xlxd, use default 127.0.0.1
otherwise use the machine own IP
4) running ambed
note:
Due to specific FTDI driver implementation, ambed must be running
with roor privilege, and cannot be run as a daemon.
So ambed will display the information and error messages in the
terminal it has been started from
plug at least one USB-3xxx USB device
# cd /ambed
# ./run
during initialisation phase, ambed will scan all USB port to discover
and configure ans report status of all available USB-3xxx devices
5) stoping ambed
find PID of ambed process, using for example ps
# ps ax | grep ambed
and kill the process
# kill xxxx
where xxxx is PID found previously.

6
ambed/run Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
# start ambed server
sudo rmmod ftdi_sio
sudo rmmod usbserial
sudo ./ambed 127.0.0.1 &

96
ambed/syslog.h Normal file
View File

@ -0,0 +1,96 @@
/*************************************************************************
** Copyright (C) 2014 Jan Pedersen <jp@jp-embedded.com>
**
** This program 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.
**
** This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/
#ifndef __syslog
#define __syslog
#include <iostream>
#include <streambuf>
#include <string>
namespace csyslog {
#include <syslog.h>
}
namespace syslog
{
struct level {
enum pri {
emerg = LOG_EMERG, // A panic condition
alert = LOG_ALERT, // A condition that should be corrected
critical= LOG_CRIT, // Critical condition, e.g, hard device error
error = LOG_ERR, // Errors
warning = LOG_WARNING, // Warning messages
notice = LOG_NOTICE, // Possibly be handled specially
info = LOG_INFO, // Informational
debug = LOG_DEBUG // For debugging program
};
};
class streambuf : public std::streambuf
{
std::string _buf;
int _level;
public:
streambuf() : _level(level::debug) { }
void level(int level) { _level = level; }
protected:
int sync()
{
if (_buf.size()) {
csyslog::syslog(_level, "%s", _buf.c_str());
_buf.erase();
}
return 0;
}
int_type overflow(int_type c)
{
if(c == traits_type::eof()) sync();
else _buf += static_cast<char>(c);
return c;
}
};
class ostream : public std::ostream
{
streambuf _logbuf;
public:
ostream() : std::ostream(&_logbuf) {}
ostream& operator<<(const level::pri lev) { _logbuf.level(lev); return *this; }
};
class redirect
{
ostream dst;
std::ostream &src;
std::streambuf * const sbuf;
public:
redirect(std::ostream & src) : src(src), sbuf(src.rdbuf(dst.rdbuf())) { dst << (&src == &std::cout ? level::info : level::error); }
~redirect() { src.rdbuf(sbuf); }
};
}
#endif