145 lines
6.0 KiB
C++

//======================================================================================================
// Copyright 2016, NaturalPoint Inc.
//======================================================================================================
#pragma once
#include <memory>
#include "AnalogSystemBuildConfig.h"
namespace AnalogSystem
{
/// <summary>
/// AnalogFrameBase is the abstract base implementation for a device's 'frame' of data.
/// A device 'frame' is a single sample of data from an analog device, one sample per
/// active channel, of the same data type, along with any header information for that sampling.
///
/// Analog frames contain a templated value for each physical signal (channel) the device reports.
/// A force plate device typically contains 6 channels (Fx,Fy,Fz,Mx,My,Mz), so the analog frame
/// would contain 6 float values, 1 for each active channel. A NIDAQ device has a user-configurable
/// active number of analog and digital channels, so the number of channels and frame types may
/// be variable.
/// </summary>
class ANALOGSYSTEM_API AnalogFrameBase
{
public:
AnalogFrameBase( int channelCount = 1 );
AnalogFrameBase( const AnalogFrameBase& src );
AnalogFrameBase& operator=( const AnalogFrameBase& src );
virtual ~AnalogFrameBase() = default;
/// <summary>template specific copy with alloc (implemented by derived class)</summary>
virtual std::unique_ptr<AnalogFrameBase> Copy() const = 0;
/// <summary>Return the number of channels in the frame</summary>
virtual const int ChannelCount() const;
/// <summary>Returns a pointer to the channel data array</summary>
void* ChannelData() const;
/// <summary>Returns a pointer to the channel data array</summary>
void* ChannelData( int channel ) { return ( (char*) mChannelData + ( channel * mChannelSize ) ); }
const void* ChannelData( int channel ) const { return ( (char*) mChannelData + ( channel * mChannelSize ) ); }
/// <summary>Gets the memory size of the channel type(in bytes)</summary>
int ChannelSize() const { return mChannelSize; }
/// <summary>Sets the frame ID</summary>
/// <param name="id">frame ID</param>
virtual void SetID( long id );
/// <summary>Gets the frame ID</summary>
virtual const long ID() const;
/// <summary>Sets the ID of the device that generated this frame</summary>
/// <param name="id">device identifier</param>
virtual void SetDeviceID( int id );
/// <summary>Gets the ID of the device that generated this frame</summary>
virtual const int DeviceID() const;
/// <summary>Sets the timestamp of the frame</summary>
/// <param name="id">device identifier</param>
virtual void SetTimestamp( double timestamp );
/// <summary>Gets the timestamp of the frame</summary>
virtual const double Timestamp() const;
/// <summary>Sets flags for this frame (frame specific bit information (e.g. trigger bit set on this frame).</summary>
/// <param name="flag">flag word</param>
virtual void SetFlag( int flag );
/// <summary>Gets device-specific flag bits for this frame</summary>
virtual const int Flag() const;
protected:
/// <summary>The number of channels</summary>
int mChannelCount;
/// <summary>Channel size (bytes)</summary>
int mChannelSize;
/// <summary>Flat array of channel data </summary>
void* mChannelData;
private:
long mID; // frame ID, usually a counter from the device source
int mDeviceID; // ID for the device associated with this data
double mTimestamp; // NTP compatible timestamp (64 bit fixed point)
int mFlag; // user defined data
};
/// <summary>
/// AnalogFrame is a type-specific implementation of a device frame.
/// </summary>
template <typename T>
class AnalogFrame : public AnalogFrameBase
{
public:
/// <summary>Initializes a new instance of the <see cref="AnalogFrame"/> class/// </summary>
/// <param name="channelCount">Number of typed data channels to allocate.</param>
AnalogFrame( int channelCount = 1 ) : AnalogFrameBase( channelCount )
{
mChannelData = new T[channelCount];
mChannelSize = sizeof( T );
::memset( mChannelData, 0, channelCount * sizeof( T ) );
}
AnalogFrame( const AnalogFrame& src ) : AnalogFrameBase( src )
{
mChannelData = new T[mChannelCount];
mChannelSize = sizeof( T );
::memcpy( this->mChannelData, src.mChannelData, (size_t) ( mChannelCount * sizeof( T ) ) );
}
AnalogFrame& operator=( const AnalogFrame& src )
{
if( this != &src )
{
__super::operator=( src );
if( mChannelData )
delete[] mChannelData;
mChannelData = new T[mChannelCount];
mChannelSize = sizeof( T );
::memcpy( this->mChannelData, src.mChannelData, mChannelCount * sizeof( T ) );
}
return *this;
}
/// <summary>Finalizes an instance of the <see cref="AnalogFrame"/> class</summary>
virtual ~AnalogFrame() { delete[] mChannelData; }
/// <summary>Allocates a new typed frame from an existing frame in the thread's memory context</summary>
std::unique_ptr<AnalogFrameBase> Copy() const override { return std::make_unique<AnalogFrame<T>>( *this ); }
/// <summary>Returns a typed pointer to the channel data array</summary>
const T* ChannelData() const { return reinterpret_cast<T*>( mChannelData ); }
T* ChannelData() { return reinterpret_cast<T*>( mChannelData ); }
/// <summary>Returns a typed pointer to the channel value</summary>
T* ChannelData( int channel ) { return &( reinterpret_cast<T*>( mChannelData )[channel] ); }
};
}