//====================================================================================================== // Copyright 2016, NaturalPoint Inc. //====================================================================================================== #pragma once #include #include "AnalogSystemBuildConfig.h" namespace AnalogSystem { /// /// 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. /// class ANALOGSYSTEM_API AnalogFrameBase { public: AnalogFrameBase( int channelCount = 1 ); AnalogFrameBase( const AnalogFrameBase& src ); AnalogFrameBase& operator=( const AnalogFrameBase& src ); virtual ~AnalogFrameBase() = default; /// template specific copy with alloc (implemented by derived class) virtual std::unique_ptr Copy() const = 0; /// Return the number of channels in the frame virtual const int ChannelCount() const; /// Returns a pointer to the channel data array void* ChannelData() const; /// Returns a pointer to the channel data array void* ChannelData( int channel ) { return ( (char*) mChannelData + ( channel * mChannelSize ) ); } const void* ChannelData( int channel ) const { return ( (char*) mChannelData + ( channel * mChannelSize ) ); } /// Gets the memory size of the channel type(in bytes) int ChannelSize() const { return mChannelSize; } /// Sets the frame ID /// frame ID virtual void SetID( long id ); /// Gets the frame ID virtual const long ID() const; /// Sets the ID of the device that generated this frame /// device identifier virtual void SetDeviceID( int id ); /// Gets the ID of the device that generated this frame virtual const int DeviceID() const; /// Sets the timestamp of the frame /// device identifier virtual void SetTimestamp( double timestamp ); /// Gets the timestamp of the frame virtual const double Timestamp() const; /// Sets flags for this frame (frame specific bit information (e.g. trigger bit set on this frame). /// flag word virtual void SetFlag( int flag ); /// Gets device-specific flag bits for this frame virtual const int Flag() const; protected: /// The number of channels int mChannelCount; /// Channel size (bytes) int mChannelSize; /// Flat array of channel data 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 }; /// /// AnalogFrame is a type-specific implementation of a device frame. /// template class AnalogFrame : public AnalogFrameBase { public: /// Initializes a new instance of the class/// /// Number of typed data channels to allocate. 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; } /// Finalizes an instance of the class virtual ~AnalogFrame() { delete[] mChannelData; } /// Allocates a new typed frame from an existing frame in the thread's memory context std::unique_ptr Copy() const override { return std::make_unique>( *this ); } /// Returns a typed pointer to the channel data array const T* ChannelData() const { return reinterpret_cast( mChannelData ); } T* ChannelData() { return reinterpret_cast( mChannelData ); } /// Returns a typed pointer to the channel value T* ChannelData( int channel ) { return &( reinterpret_cast( mChannelData )[channel] ); } }; }