/* * BinaryEncoder.hpp * * Created on: 23 июн. 2023 г. * Author: titov */ #ifndef UMLIBRARY_DRIVER_BINARYENCODER_HPP_ #define UMLIBRARY_DRIVER_BINARYENCODER_HPP_ #include #include #include "IEncoder.hh" #include "../communication/format/BinaryDataPublisher.hh" #include "../common/DoubleBuffer.hpp" #include "../communication/format/BinaryHelpers.hh" #include #include "../math/math_inc.hh" #include namespace driver { namespace detail { struct BinaryEncoderInterface : public IEncoder, public communication::IBinaryDataSubscriber {}; //!Базовый класс драйвера энкодера, обновляющего свои значения в момент обновления. template class BinaryEncoderBase : public BinaryEncoderInterface { public: typedef communication::format::bits::bitsize bitsize; BinaryEncoderBase( bitsize angle_size, bitsize turn_size ); //!Функция возращает номер оборота. Turn getTurn() const; //!Функция возращает угол в радианах от 0 до 2*pi или NaN. Angle getAngle() const; //!Метод позволяет получить консистентные данные позиции энкодера в формате (оборот, угол). std::pair getPosition() const; protected: typedef FrameType frame; mutable std::atomic point; private: const bitsize turn_offset; const frame turn_mask; const frame angle_mask; const Angle angle_cost; }; template inline driver::detail::BinaryEncoderBase::BinaryEncoderBase( bitsize angle_size, bitsize turn_size ) : turn_offset(angle_size), turn_mask( ( 1ull << turn_size ) - 1ull ), angle_mask( ( 1ull << angle_size ) - 1ull), angle_cost( math::constants::pi2 / std::pow(2.0f, float(angle_size) ) ), point() { point.store(0); } template inline driver::IEncoder::Turn driver::detail::BinaryEncoderBase::getTurn() const { frame current_frame = point.load(); Turn turn = ( current_frame >> turn_offset ) & turn_mask; return turn; } template inline driver::IEncoder::Angle driver::detail::BinaryEncoderBase::getAngle() const { frame current_frame = point.load(); Angle angle = ( current_frame & angle_mask ) * angle_cost; return angle; } template std::pair< driver::IEncoder::Turn, driver::IEncoder::Angle > driver::detail::BinaryEncoderBase::getPosition() const { frame current_frame = point.load(); Turn turn = ( current_frame >> turn_offset ) & turn_mask; Angle angle = ( current_frame & angle_mask ) * angle_cost; return std::pair( turn, angle ); } //!Драйвер энкодера в бинарном формате. template class BinaryEncoder : public BinaryEncoderBase { public: typedef communication::format::bits::bitsize bitsize; BinaryEncoder( bitsize angle_size, bitsize turn_size ); /*! * data - угол и оборот в бинароном виде, угол со смещением 0. */ void read( const void * data, std::size_t size ) override; }; template BinaryEncoder::BinaryEncoder( bitsize angle_size, bitsize turn_size ) : BinaryEncoderBase(angle_size, turn_size) {} template void driver::detail::BinaryEncoder::read( const void * data, std::size_t size ) { typename BinaryEncoderBase::frame new_frame; std::memcpy( &new_frame, data, sizeof(new_frame) ); BinaryEncoderBase::point.store( new_frame ); } //!Драйвер энкодера в бинарном формате, включает инверсию входных данных для изменения направления вращения. template class BinaryEncoderInverted : public BinaryEncoderBase { public: typedef communication::format::bits::bitsize bitsize; BinaryEncoderInverted( bitsize angle_size, bitsize turn_size ); void read( const void * data, std::size_t size ) override; }; template BinaryEncoderInverted::BinaryEncoderInverted( bitsize angle_size, bitsize turn_size ) : BinaryEncoderBase(angle_size, turn_size) {} template void driver::detail::BinaryEncoderInverted::read( const void * data, std::size_t size ) { typename BinaryEncoderBase::frame new_frame; std::memcpy( &new_frame, data, sizeof(new_frame) ); BinaryEncoderBase::point.store( ~new_frame ); } //!Драйвер энкодера в формате кода грей. template class BinaryEncoderGray : public BinaryEncoderBase { public: typedef communication::format::bits::bitsize bitsize; BinaryEncoderGray( bitsize angle_size, bitsize turn_size ); void read( const void * data, std::size_t size ) override; }; //!Драйвер энкодера в формате кода грей, включает инверсию входных данных для изменения направления вращения. template class BinaryEncoderGrayInverted : BinaryEncoderBase { public: typedef communication::format::bits::bitsize bitsize; BinaryEncoderGrayInverted( bitsize angle_size, bitsize turn_size ); void read( const void * data, std::size_t size ) override; }; }} #endif /* UMLIBRARY_DRIVER_BINARYENCODER_HPP_ */