962 lines
30 KiB
C++
962 lines
30 KiB
C++
/**
|
|
* yateradio.h
|
|
* Radio library
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
*
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
* Copyright (C) 2011-2014 Null Team
|
|
* Copyright (C) 2015 LEGBA Inc
|
|
*
|
|
* This software is distributed under multiple licenses;
|
|
* see the COPYING file in the main directory for licensing
|
|
* information for this specific distribution.
|
|
*
|
|
* This use of this software may be subject to additional restrictions.
|
|
* See the LEGAL file in the main directory for details.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef __YATERADIO_H
|
|
#define __YATERADIO_H
|
|
|
|
#include <yateclass.h>
|
|
#include <yatexml.h>
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#ifdef LIBYRADIO_EXPORTS
|
|
#define YRADIO_API __declspec(dllexport)
|
|
#else
|
|
#ifndef LIBYRADIO_STATIC
|
|
#define YRADIO_API __declspec(dllimport)
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* _WINDOWS */
|
|
|
|
#ifndef YRADIO_API
|
|
#define YRADIO_API
|
|
#endif
|
|
|
|
|
|
namespace TelEngine {
|
|
|
|
class GSML3Codec; // GSM Layer codec
|
|
class RadioCapability; // Radio device capabilities
|
|
class RadioInterface; // Generic radio interface
|
|
|
|
class YRADIO_API GSML3Codec
|
|
{
|
|
YNOCOPY(GSML3Codec);
|
|
public:
|
|
/**
|
|
* Codec flags
|
|
*/
|
|
enum Flags {
|
|
XmlDumpMsg = 0x01,
|
|
XmlDumpIEs = 0x02,
|
|
MSCoder = 0x04,
|
|
};
|
|
|
|
/**
|
|
* Codec return status
|
|
*/
|
|
enum Status {
|
|
NoError = 0,
|
|
MsgTooShort,
|
|
UnknownProto,
|
|
ParserErr,
|
|
MissingParam,
|
|
IncorrectOptionalIE,
|
|
IncorrectMandatoryIE,
|
|
MissingMandatoryIE,
|
|
UnknownMsgType,
|
|
};
|
|
|
|
/**
|
|
* Protocol discriminator according to ETSI TS 124 007 V11.0.0, section 11.2.3.1.1
|
|
*/
|
|
enum Protocol {
|
|
GCC = 0x00, // Group Call Control
|
|
BCC = 0x01, // Broadcast Call Control
|
|
EPS_SM = 0x02, // EPS Session Management
|
|
CC = 0x03, // Call Control; Call Related SS messages
|
|
GTTP = 0x04, // GPRS Transparent Transport Protocol (GTTP)
|
|
MM = 0x05, // Mobility Management
|
|
RRM = 0x06, // Radio Resources Management
|
|
EPS_MM = 0x07, // EPS Mobility Management
|
|
GPRS_MM = 0x08, // GPRS Mobility Management
|
|
SMS = 0x09, // SMS
|
|
GPRS_SM = 0x0a, // GPRS Session Management
|
|
SS = 0x0b, // Non Call Related SS messages
|
|
LCS = 0x0c, // Location services
|
|
Extension = 0x0e, // reserved for extension of the PD to one octet length
|
|
Test = 0x0f, // used by tests procedures described in 3GPP TS 44.014, 3GPP TS 34.109 and 3GPP TS 36.509
|
|
Unknown = 0xff,
|
|
};
|
|
|
|
/**
|
|
* IE types
|
|
*/
|
|
enum Type {
|
|
NoType = 0,
|
|
T,
|
|
V,
|
|
TV,
|
|
LV,
|
|
TLV,
|
|
LVE,
|
|
TLVE,
|
|
};
|
|
|
|
/**
|
|
* Type of XML data to generate
|
|
*/
|
|
enum XmlType {
|
|
Skip,
|
|
XmlElem,
|
|
XmlRoot,
|
|
};
|
|
|
|
/**
|
|
* EPS Security Headers
|
|
*/
|
|
enum EPSSecurityHeader {
|
|
PlainNAS = 0x00,
|
|
IntegrityProtect = 0x01,
|
|
IntegrityProtectCiphered = 0x02,
|
|
IntegrityProtectNewEPSCtxt = 0x03,
|
|
IntegrityProtectCipheredNewEPSCtxt = 0x04,
|
|
ServiceRequestHeader = 0xa0,
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
GSML3Codec(DebugEnabler* dbg = 0);
|
|
|
|
/**
|
|
* Decode layer 3 message payload
|
|
* @param in Input buffer containing the data to be decoded
|
|
* @param len Length of input buffer
|
|
* @param out XmlElement into which the decoded data is returned
|
|
* @param params Encoder parameters
|
|
* @return Parsing result: 0 (NoError) if succeeded, error status otherwise
|
|
*/
|
|
unsigned int decode(const uint8_t* in, unsigned int len, XmlElement*& out, const NamedList& params = NamedList::empty());
|
|
|
|
/**
|
|
* Encode a layer 3 message
|
|
* @param in Layer 3 message in XML form
|
|
* @param out Output buffer into which to put encoded data
|
|
* @param params Encoder parameters
|
|
* @return Parsing result: 0 (NoError) if succeeded, error status otherwise
|
|
*/
|
|
unsigned int encode(const XmlElement* in, DataBlock& out, const NamedList& params = NamedList::empty());
|
|
|
|
/**
|
|
* Decode layer 3 message from an existing XML
|
|
* @param xml XML which contains layer 3 messages to decode and into which the decoded XML will be put
|
|
* @param params Decoder parameters
|
|
* @return Parsing result: 0 (NoError) if succeeded, error status otherwise
|
|
*/
|
|
unsigned int decode(XmlElement* xml, const NamedList& params = NamedList::empty());
|
|
|
|
/**
|
|
* Encode a layer 3 message from an existing XML
|
|
* @param xml XML which contains a layer 3 message in XML form. The message will be replaced with its encoded buffer
|
|
* @param params Encoder parameters
|
|
* @return Parsing result: 0 (NoError) if succeeded, error status otherwise
|
|
*/
|
|
unsigned int encode(XmlElement* xml, const NamedList& params = NamedList::empty());
|
|
|
|
/**
|
|
* Set data used in debug
|
|
* @param enabler The DebugEnabler to use (0 to to use the engine)
|
|
* @param ptr Pointer to print, 0 to use the codec pointer
|
|
*/
|
|
void setCodecDebug(DebugEnabler* enabler = 0, void* ptr = 0);
|
|
|
|
/**
|
|
* Retrieve codec flags
|
|
* @return Codec flags
|
|
*/
|
|
inline uint8_t flags() const
|
|
{ return m_flags; }
|
|
|
|
/**
|
|
* Set codec flags
|
|
* @param flgs Flags to set
|
|
* @param reset Reset flags before setting these ones
|
|
*/
|
|
inline void setFlags(uint8_t flgs, bool reset = false)
|
|
{
|
|
if (reset)
|
|
resetFlags();
|
|
m_flags |= flgs;
|
|
}
|
|
|
|
/**
|
|
* Reset codec flags
|
|
* @param flgs Flags to reset. If 0, all flags are reset
|
|
*/
|
|
inline void resetFlags(uint8_t flgs = 0)
|
|
{
|
|
if (flgs)
|
|
m_flags &= ~flgs;
|
|
else
|
|
m_flags = 0;
|
|
}
|
|
|
|
/**
|
|
* Activate printing of debug messages
|
|
* @param on True to activate, false to disable
|
|
*/
|
|
inline void setPrintDbg(bool on = false)
|
|
{ m_printDbg = on; }
|
|
|
|
/**
|
|
* Get printing of debug messages flag
|
|
* @return True if debugging is activated, false otherwise
|
|
*/
|
|
inline bool printDbg() const
|
|
{ return m_printDbg; }
|
|
|
|
/**
|
|
* Get DebugEnabler used by this codec
|
|
* @return DebugEnabler used by the codec
|
|
*/
|
|
inline DebugEnabler* dbg() const
|
|
{ return m_dbg; }
|
|
|
|
/**
|
|
* Retrieve the codec pointer used for debug messages
|
|
* @return Codec pointer used for debug messages
|
|
*/
|
|
inline void* ptr() const
|
|
{ return m_ptr; }
|
|
|
|
/**
|
|
* Decode GSM 7bit buffer
|
|
* @param buf Input buffer
|
|
* @param len Input buffer length
|
|
* @param text Destination text
|
|
* @param heptets Maximum number of heptets in buffer
|
|
*/
|
|
static void decodeGSM7Bit(unsigned char* buf, unsigned int len, String& text,
|
|
unsigned int heptets = (unsigned int)-1);
|
|
|
|
/**
|
|
* Encode GSM 7bit buffer
|
|
* @param text Input text
|
|
* @param buf Destination buffer
|
|
* @return True if all characters were encoded correctly
|
|
*/
|
|
static bool encodeGSM7Bit(const String& text, DataBlock& buf);
|
|
|
|
/**
|
|
* IE types dictionary
|
|
*/
|
|
static const TokenDict s_typeDict[];
|
|
|
|
/**
|
|
* L3 Protocols dictionary
|
|
*/
|
|
static const TokenDict s_protoDict[];
|
|
|
|
/**
|
|
* EPS Security Headers dictionary
|
|
*/
|
|
static const TokenDict s_securityHeaders[];
|
|
|
|
/**
|
|
* Errors dictionary
|
|
*/
|
|
static const TokenDict s_errorsDict[];
|
|
|
|
/**
|
|
* Mobility Management reject causes dictionary
|
|
*/
|
|
static const TokenDict s_mmRejectCause[];
|
|
|
|
/**
|
|
* GPRS Mobility Management reject causes dictionary
|
|
*/
|
|
static const TokenDict s_gmmRejectCause[];
|
|
|
|
private:
|
|
|
|
unsigned int decodeXml(XmlElement* xml, const NamedList& params, const String& pduTag);
|
|
unsigned int encodeXml(XmlElement* xml, const NamedList& params, const String& pduTag);
|
|
void printDbg(int dbgLevel, const uint8_t* in, unsigned int len, XmlElement* xml, bool encode = false);
|
|
|
|
uint8_t m_flags; // Codec flags
|
|
// data used for debugging messages
|
|
DebugEnabler* m_dbg;
|
|
void* m_ptr;
|
|
// activate debug
|
|
bool m_printDbg;
|
|
};
|
|
|
|
|
|
/**
|
|
* @short Radio device capabilities
|
|
* Radio capability object describes the parameter ranges of the radio handware.
|
|
*/
|
|
class YRADIO_API RadioCapability
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
RadioCapability();
|
|
|
|
unsigned maxPorts; // Available number of ports
|
|
unsigned currPorts; // Number of used (available) ports
|
|
uint64_t maxTuneFreq; // Maximum allowed tuning frequency (in Hz)
|
|
uint64_t minTuneFreq; // Minimum allowed tuning frequency (in Hz)
|
|
unsigned maxSampleRate; // Maximum allowed sampling rate (in Hz)
|
|
unsigned minSampleRate; // Minimum allowed sampling rate (in Hz)
|
|
unsigned maxFilterBandwidth; // Maximum allowed anti-alias filter bandwidth (in Hz)
|
|
unsigned minFilterBandwidth; // Minimum allowed anti-alias filter bandwidth (in Hz)
|
|
unsigned rxLatency; // Estimated radio latency (in samples)
|
|
unsigned txLatency; // Estimated transmit latency (in samples)
|
|
};
|
|
|
|
|
|
/**
|
|
* Keeps a buffer pointer with offset and valid samples
|
|
* @short A buffer description
|
|
*/
|
|
class RadioBufDesc
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline RadioBufDesc()
|
|
: samples(0), offs(0), valid(0)
|
|
{}
|
|
|
|
/**
|
|
* Reset the buffer
|
|
* @param value Offset and valid samples value
|
|
*/
|
|
inline void reset(unsigned int value = 0)
|
|
{ offs = valid = value; }
|
|
|
|
/**
|
|
* Reset the buffer
|
|
* @param offset New offset
|
|
* @param validS New valid samples value
|
|
*/
|
|
inline void reset(unsigned int offset, unsigned int validS) {
|
|
offs = offset;
|
|
valid = validS;
|
|
}
|
|
|
|
/**
|
|
* Check if the buffer is valid
|
|
* @param minSamples Required minimum number of valid samples
|
|
* @return True if valid, false otherwise
|
|
*/
|
|
inline bool validSamples(unsigned int minSamples) const
|
|
{ return !minSamples || minSamples >= offs || minSamples >= valid; }
|
|
|
|
float* samples; // Current read buffer
|
|
unsigned int offs; // Current buffer offset (in sample periods)
|
|
unsigned int valid; // The number of valid samples in buffer
|
|
};
|
|
|
|
|
|
/**
|
|
* Keeps buffers used by RadioInterface::read()
|
|
* @short RadioInterface read buffers
|
|
*/
|
|
class RadioReadBufs : public GenObject
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param len Single buffer length (in sample periods)
|
|
* @param validThres Optional threshold for valid samples. Used when read timestamp
|
|
* data is in the future and a portion of the buffer need to be reset.
|
|
* If valid samples are below threshold data won't be set or copied
|
|
*/
|
|
inline RadioReadBufs(unsigned int len = 0, unsigned int validThres = 0)
|
|
: m_bufSamples(len), m_validMin(validThres)
|
|
{}
|
|
|
|
/**
|
|
* Reset buffers
|
|
* @param len Single buffer length (in sample periods)
|
|
* @param validThres Optional threshold for valid samples
|
|
*/
|
|
inline void reset(unsigned int len, unsigned int validThres) {
|
|
m_bufSamples = len;
|
|
m_validMin = validThres;
|
|
crt.reset();
|
|
aux.reset();
|
|
extra.reset();
|
|
}
|
|
|
|
/**
|
|
* Retrieve the length of a single buffer
|
|
* @return Buffer length (in sample periods)
|
|
*/
|
|
inline unsigned int bufSamples() const
|
|
{ return m_bufSamples; }
|
|
|
|
/**
|
|
* Check if a given buffer is full (offset is at least buffer length)
|
|
* @param buf Buffer to check
|
|
* @return True if the given buffer is full, false otherwise
|
|
*/
|
|
inline bool full(RadioBufDesc& buf) const
|
|
{ return buf.offs >= m_bufSamples; }
|
|
|
|
/**
|
|
* Check if a given is valid (have enough valid samples)
|
|
* @param buf Buffer to check
|
|
* @return True if the given buffer is valid, false otherwise
|
|
*/
|
|
inline bool valid(RadioBufDesc& buf) const
|
|
{ return buf.validSamples(m_validMin); }
|
|
|
|
/**
|
|
* Dump data for debug purposes
|
|
* @param buf Destination buffer
|
|
* @return Destination buffer reference
|
|
*/
|
|
String& dump(String& buf);
|
|
|
|
RadioBufDesc crt;
|
|
RadioBufDesc aux;
|
|
RadioBufDesc extra;
|
|
|
|
protected:
|
|
unsigned int m_bufSamples; // Buffers length in sample periods
|
|
unsigned int m_validMin; // Valid samples threshold
|
|
};
|
|
|
|
|
|
/**
|
|
* @short Generic radio interface
|
|
*
|
|
* @note Some parameters are quantized by the radio hardware. If the caller requests a parameter
|
|
* value that cannot be matched exactly, the setting method will set the parameter to the
|
|
* best avaiable match and return "NotExact". For such parameters, there is a corresponding
|
|
* readback method to get the actual value used.
|
|
*
|
|
* @note If a method does not include a radio port number, then that method applies to all connected ports.
|
|
*
|
|
* @note The interface may control multiple radios, with each one appearing as a port. However, in this case,
|
|
* - all radios are to be synched on the sample clock
|
|
* - all radios are to be of the same hardware type
|
|
*
|
|
* @note If the performance of the radio hardware changes, the API indicates this with the RFHardwareChange
|
|
* flag. If this flag appears in a result code, the application should:
|
|
* - read a new RadioCapabilties object
|
|
* - revisit all of the application-level parameter settings on the radio
|
|
* - check the status() method on each port to identify single-port errors
|
|
*/
|
|
class YRADIO_API RadioInterface : public RefObject, public DebugEnabler
|
|
{
|
|
YCLASS(RadioInterface,RefObject);
|
|
public:
|
|
/** Error code bit positions in the error code mask. */
|
|
enum ErrorCode {
|
|
NoError = 0,
|
|
Failure = (1 << 1), // Unknown error
|
|
HardwareIOError = (1 << 2), // Communication error with HW
|
|
NotInitialized = (1 << 3), // Interface not initialized
|
|
NotSupported = (1 << 4), // Feature not supported
|
|
NotCalibrated = (1 << 5), // The radio is not calibrated
|
|
TooEarly = (1 << 6), // Timestamp is in the past
|
|
TooLate = (1 << 7), // Timestamp is in the future
|
|
OutOfRange = (1 << 8), // A requested parameter setting is out of range
|
|
NotExact = (1 << 9), // The affected value is not an exact match to the requested one
|
|
DataLost = (1 << 10), // Received data lost due to slow reads
|
|
Saturation = (1 << 11), // Data contain values outside of +/-1+/-j
|
|
RFHardwareFail = (1 << 12), // Failure in RF hardware
|
|
RFHardwareChange = (1 << 13), // Change in RF hardware, not outright failure
|
|
EnvironmentalFault = (1 << 14), // Environmental spec exceeded for radio HW
|
|
InvalidPort = (1 << 15), // Invalid port number
|
|
Pending = (1 << 16), // Operation is pending
|
|
Cancelled = (1 << 17), // Operation cancelled
|
|
Timeout = (1 << 18), // Operation timeout
|
|
// Masks
|
|
// Errors requiring radio or port shutdown
|
|
FatalErrorMask = HardwareIOError | RFHardwareFail | EnvironmentalFault | Failure,
|
|
// Errors that can be cleared
|
|
ClearErrorMask = TooEarly | TooLate | NotExact | DataLost | Saturation |
|
|
InvalidPort | Timeout,
|
|
// Errors that are specific to a single call
|
|
LocalErrorMask = NotInitialized | NotCalibrated | TooEarly | TooLate | OutOfRange |
|
|
NotExact | DataLost | Saturation | RFHardwareChange | InvalidPort,
|
|
};
|
|
|
|
/**
|
|
* Retrieve the radio device path
|
|
* @param devicePath Destination buffer
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getInterface(String& devicePath) const
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Retrieve radio capabilities
|
|
* @return RadioCapability pointer, 0 if unknown or not implemented
|
|
*/
|
|
virtual const RadioCapability* capabilities() const
|
|
{ return m_radioCaps; }
|
|
|
|
/**
|
|
* Initialize the radio interface.
|
|
* Any attempt to transmit or receive prior to this operation will return NotInitialized.
|
|
* @param params Optional parameters list
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int initialize(const NamedList& params = NamedList::empty()) = 0;
|
|
|
|
/**
|
|
* Set radio loopback
|
|
* @param name Loopback name (NULL for none)
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setLoopback(const char* name = 0)
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Set multiple interface parameters.
|
|
* Each command must start with 'cmd:' to allow the code to detect unhandled commands.
|
|
* Command sub-params should not start with the prefix
|
|
* @param params Parameters list
|
|
* @param shareFate True to indicate all parameters share the fate
|
|
* (return on first error, except for Pending), false to process all
|
|
* @return Error code (0 on success). Failed command(s) will be set in the list
|
|
* with cmd_name.code=error_code
|
|
*/
|
|
virtual unsigned int setParams(NamedList& params, bool shareFate = true) = 0;
|
|
|
|
/**
|
|
* Update (set/reset) interface data dump
|
|
* @param dir Direction to update. 0: both, negative: RX only, positive: TX only
|
|
* @param level Dump level to update. 0: both, negative: interface level (data
|
|
* sent/received by the upper layer), positive: device level (data sent to or
|
|
* read from radio device)
|
|
* @param params Optional parameters
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setDataDump(int dir = 0, int level = 0,
|
|
const NamedList* params = 0) = 0;
|
|
|
|
/**
|
|
* Run internal calibration procedures and/or load calibration parmameters
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int calibrate()
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Set the number of ports to be used
|
|
* @param count The number of ports to be used
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setPorts(unsigned count) = 0;
|
|
|
|
/**
|
|
* Return any persistent error codes.
|
|
* ("Persistent" means a condition of the radio interface itself,
|
|
* as opposed to a status code related to a specific method call)
|
|
* @param port Port number to check, or -1 for all ports OR'd together
|
|
* @return Error(s) mask
|
|
*/
|
|
virtual unsigned int status(int port = -1) const = 0;
|
|
|
|
/**
|
|
* Clear all error codes that can be cleared.
|
|
* Note the not all codes are clearable, like HW failures for example.
|
|
*/
|
|
virtual void clearErrors()
|
|
{ m_lastErr &= ~ClearErrorMask; }
|
|
|
|
/**
|
|
* Send a frame of complex samples at a given time, interleaved IQ format.
|
|
* If there are gaps in the sample stream, the RadioInterface must zero-fill.
|
|
* All ports are sent together in interleaved format; example:
|
|
* I0 Q0 I1 Q1 I2 Q2 I0 Q0 I1 Q1 I2 Q2, etc for a 3-port system
|
|
* Block until the send is complete.
|
|
* Return TooEarly if the blocking time would be too long.
|
|
* Return TooLate if any of the block is in the past.
|
|
* @param when Time to schedule the transmission
|
|
* @param samples Data to send (array of 2 * size * ports floats, interleaved IQ)
|
|
* @param size The number of sample periods in the samples array
|
|
* @param powerScale Optional pointer to power scale value
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int send(uint64_t when, float* samples, unsigned size,
|
|
float* powerScale = 0) = 0;
|
|
|
|
/**
|
|
* Receive the next available samples and associated timestamp.
|
|
* All ports are received together in interleaved format.
|
|
* e.g: I0 Q0 I1 Q1 I2 Q2 I0 Q0 I1 Q1 I2 Q2, etc for a 3-port system.
|
|
* The method will wait for proper timestamp (to be at least requested timestamp).
|
|
* The caller must increase the timestamp after succesfull read.
|
|
* The method may return less then requested size.
|
|
* @param when Input: current timestamp. Output: read data timestamp
|
|
* @param samples Destination buffer (array of 2 * size * ports floats, interleaved IQ)
|
|
* @param size Input: requested number of samples. Output: actual number of read samples
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int recv(uint64_t& when, float* samples, unsigned& size) = 0;
|
|
|
|
/**
|
|
* Receive the next available samples and associated timestamp.
|
|
* Compensate timestamp difference.
|
|
* Copy any valid data in the future to auxiliary buffers.
|
|
* Adjust the timestamp (no need for the caller to do it).
|
|
* Handles buffer rotation also.
|
|
* All sample counters (length/offset) are expected in sample periods.
|
|
* @param when Input: current timestamp. Output: next read data timestamp
|
|
* @param bufs Buffers to use
|
|
* @param skippedBufs The number of skipped full buffers
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int read(uint64_t& when, RadioReadBufs& bufs,
|
|
unsigned int& skippedBufs);
|
|
|
|
/**
|
|
* Get the time of the data currently being received from the radio
|
|
* @param when Destination buffer for requested radio time
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getRxTime(uint64_t& when) const = 0;
|
|
|
|
/**
|
|
* Get the time of the the data currently being sent to the radio
|
|
* @param when Destination buffer for requested radio time
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getTxTime(uint64_t& when) const = 0;
|
|
|
|
/**
|
|
* Set the frequency offset
|
|
* @param offs Frequency offset to set
|
|
* @param newVal Optional pointer to value set by interface (requested value may
|
|
* be adjusted to fit specific device value)
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setFreqOffset(int offs, int* newVal = 0) = 0;
|
|
|
|
/**
|
|
* Set the sample rate
|
|
* @param hz Sample rate value in Hertz
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setSampleRate(uint64_t hz) = 0;
|
|
|
|
/**
|
|
* Get the actual sample rate
|
|
* @param hz Sample rate value in Hertz
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getSampleRate(uint64_t& hz) const = 0;
|
|
|
|
/**
|
|
* Set the anti-aliasing filter BW
|
|
* @param hz Anti-aliasing filter value in Hertz
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setFilter(uint64_t hz) = 0;
|
|
|
|
/**
|
|
* Get the actual anti-aliasing filter BW
|
|
* @param hz Anti-aliasing filter value in Hertz
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getFilterWidth(uint64_t& hz) const = 0;
|
|
|
|
/**
|
|
* Set the transmit frequency in Hz
|
|
* @param hz Transmit frequency value
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setTxFreq(uint64_t hz) = 0;
|
|
|
|
/**
|
|
* Readback actual transmit frequency
|
|
* @param hz Transmit frequency value
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getTxFreq(uint64_t& hz) const = 0;
|
|
|
|
/**
|
|
* Set the output power in dBm.
|
|
* This is power per active port, compensating for internal gain differences.
|
|
* @param dBm The output power to set
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setTxPower(unsigned dBm) = 0;
|
|
|
|
/**
|
|
* Set the receive frequency in Hz
|
|
* @param hz Receive frequency value
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setRxFreq(uint64_t hz) = 0;
|
|
|
|
/**
|
|
* Readback actual receive frequency
|
|
* @param hz Receive frequency value
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int getRxFreq(uint64_t& hz) const = 0;
|
|
|
|
/**
|
|
* Set the transmit pre-mixer gain in dB wrt max
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setTxGain1(int val, unsigned port)
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Set the transmit post-mixer gain in dB wrt max
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setTxGain2(int val, unsigned port)
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Set the receive pre-mixer gain in dB wrt max
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setRxGain1(int val, unsigned port)
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Set the receive post-mixer gain in dB wrt max
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setRxGain2(int val, unsigned port)
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Automatic tx/rx gain setting
|
|
* Set post mixer value. Return a value to be used by upper layer
|
|
* @param tx Direction
|
|
* @param val Value to set
|
|
* @param port Port to use
|
|
* @param newVal Optional pointer to value to use for calculation by the upper layer
|
|
* @return Error code (0 on success)
|
|
*/
|
|
virtual unsigned int setGain(bool tx, int val, unsigned int port,
|
|
int* newVal = 0) const
|
|
{ return NotSupported; }
|
|
|
|
/**
|
|
* Retrieve the interface name
|
|
* @return Interface name
|
|
*/
|
|
virtual const String& toString() const;
|
|
|
|
/**
|
|
* Retrieve the error string associated with a specific code
|
|
* @param code Error code
|
|
* @param defVal Optional default value to retrieve if not found
|
|
* @return Valid TokenDict pointer
|
|
*/
|
|
static inline const char* errorName(int code, const char* defVal = 0)
|
|
{ return lookup(code,errorNameDict(),defVal); }
|
|
|
|
/**
|
|
* Retrieve the error name dictionary
|
|
* @return Valid TokenDict pointer
|
|
*/
|
|
static const TokenDict* errorNameDict();
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param name Interface name
|
|
*/
|
|
inline RadioInterface(const char* name)
|
|
: m_lastErr(0), m_totalErr(0), m_radioCaps(0), m_name(name)
|
|
{ debugName(m_name); }
|
|
|
|
unsigned int m_lastErr; // Last error that appeared during functioning
|
|
unsigned int m_totalErr; // All the errors that appeared
|
|
RadioCapability* m_radioCaps; // Radio capabilities
|
|
|
|
private:
|
|
String m_name;
|
|
};
|
|
|
|
|
|
/**
|
|
* @short Radio data file header
|
|
* This class describes records in radio data files
|
|
*/
|
|
class YRADIO_API RadioDataDesc
|
|
{
|
|
public:
|
|
/**
|
|
* Samples data type
|
|
*/
|
|
enum ElementType {
|
|
Float = 0,
|
|
Int16 = 1,
|
|
};
|
|
|
|
/**
|
|
* Timestamp type
|
|
*/
|
|
enum TsType {
|
|
TsApp = 0, // Application level timestamp
|
|
TsBoard = 1, // Board (device) level timestamp
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param eType Element type
|
|
* @param tsType Racords timestamp type
|
|
* @param sLen Sample length in elements
|
|
* @param ports Number of device ports
|
|
*/
|
|
inline RadioDataDesc(uint8_t eType = Float, uint8_t tsType = TsApp,
|
|
uint8_t sLen = 2, uint8_t ports = 1)
|
|
: m_elementType(eType), m_sampleLen(sLen), m_ports(ports ? ports : 1),
|
|
m_tsType(tsType),
|
|
#ifdef LITTLE_ENDIAN
|
|
m_littleEndian(true)
|
|
#else
|
|
m_littleEndian(false)
|
|
#endif
|
|
{
|
|
m_signature[0] = 'Y';
|
|
m_signature[1] = 'R';
|
|
m_signature[2] = 0;
|
|
}
|
|
|
|
uint8_t m_signature[3]; // File signature
|
|
uint8_t m_elementType; // Element data type
|
|
uint8_t m_sampleLen; // Sample length in elements
|
|
uint8_t m_ports; // The number of ports
|
|
uint8_t m_tsType; // Records timestamp type
|
|
bool m_littleEndian; // Endiannes
|
|
};
|
|
|
|
|
|
/**
|
|
* @short Radio data file helper
|
|
* This class implements utilities used to read or write radio data to/from file
|
|
* The String contains object name used for debug
|
|
*/
|
|
class YRADIO_API RadioDataFile : public String
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param name Name used for debug
|
|
* @param dropOnError Terminate on file/data error
|
|
*/
|
|
RadioDataFile(const char* name, bool dropOnError = true);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~RadioDataFile();
|
|
|
|
/**
|
|
* Retrieve data description
|
|
* @return Data description object
|
|
*/
|
|
inline const RadioDataDesc& desc() const
|
|
{ return m_header; }
|
|
|
|
/**
|
|
* Check if enabled
|
|
* @return True if enabled, false otherwise
|
|
*/
|
|
inline bool valid() const
|
|
{ return m_file.valid(); }
|
|
|
|
/**
|
|
* Check if machine endiannes is the same as file endiannes
|
|
* @return True if they are the same
|
|
*/
|
|
inline bool sameEndian() const
|
|
{ return m_littleEndian == m_header.m_littleEndian; }
|
|
|
|
/**
|
|
* Open a file for read/write. Terminate current data dump if any.
|
|
* Write or read the file header
|
|
* @param fileName File to open
|
|
* @param data Data description. Pass a NULL pointer for read or valid data for write
|
|
* @param dbg Optional DebugEnabler pointer (show debug on failure)
|
|
* @param error Optional destination for file operation error code
|
|
* @return True on success, false on failure (read: error set to 0 means
|
|
* invalid file size, write: error set to 0 means invalid header)
|
|
*/
|
|
bool open(const char* fileName, const RadioDataDesc* data,
|
|
DebugEnabler* dbg = 0, int* error = 0);
|
|
|
|
/**
|
|
* Write a record to file
|
|
* @param ts Record timestamp
|
|
* @param buf Buffer to write
|
|
* @param len Buffer length in bytes
|
|
* @param dbg Optional DebugEnabler pointer (show debug on failure)
|
|
* @param error Optional destination for file operation error code
|
|
* @return True on success, false on failure (error set to 0 means invalid length)
|
|
*/
|
|
bool write(uint64_t ts, const void* buf, uint32_t len, DebugEnabler* dbg = 0,
|
|
int* error = 0);
|
|
|
|
/**
|
|
* Read a record from file
|
|
* The method don't check the record length, this must be done by the upper layer
|
|
* @param ts Record timestamp
|
|
* @param buffer Destination buffer. It will be resized to read data length
|
|
* @param dbg Optional DebugEnabler pointer (show debug on failure)
|
|
* @param error Optional destination for file operation error code
|
|
* @return True on success (empty buffer means file EOF),
|
|
* false on failure (error set to 0 means invalid record size)
|
|
*/
|
|
bool read(uint64_t& ts, DataBlock& buffer, DebugEnabler* dbg = 0, int* error = 0);
|
|
|
|
/**
|
|
* Terminate data dump, close file
|
|
* @param dbg Optional DebugEnabler pointer (show terminate message)
|
|
*/
|
|
void terminate(DebugEnabler* dbg = 0);
|
|
|
|
/**
|
|
* Convert endiannes
|
|
* @param buf The buffer to convert
|
|
* @param bytes Element length in bytes
|
|
* @return True on success, false if not supported
|
|
*/
|
|
static bool fixEndian(DataBlock& buf, unsigned int bytes);
|
|
|
|
protected:
|
|
bool ioError(bool send, DebugEnabler* dbg, int* error, const char* extra);
|
|
|
|
bool m_littleEndian; // Machine endiannes
|
|
bool m_dropOnError; // Terminate (close file) on error
|
|
uint32_t m_chunkSize; // Item size (used to check data validity)
|
|
RadioDataDesc m_header; // File header
|
|
File m_file; // File to use
|
|
DataBlock m_writeBuf;
|
|
};
|
|
|
|
}; // namespace TelEngine
|
|
|
|
#endif /* __YATERADIO_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|