#pragma once #include "components/ffmsep/cpdecoder.hh" #include "components/ffmsep/tactile/tacdec.hh" #include #include #include #include #include #include #include #include namespace ffmsep { struct DecodedFrame { CPFrame frame; std::chrono::steady_clock::time_point received_at{}; std::int64_t pts = 0; std::optional tactile; std::vector tactile_pressures; std::optional tactile_matrix_size; }; using namespace std::chrono_literals; struct CPStreamConfig { std::string port; std::uint32_t baudrate = 115200; serial::Timeout timeout = serial::Timeout::simpleTimeout(50); serial::bytesize_t bytesize = serial::eightbits; serial::parity_t parity = serial::parity_none; serial::stopbits_t stopbits = serial::stopbits_one; serial::flowcontrol_t flowcontrol = serial::flowcontrol_none; std::size_t read_chunk_size = 256; std::size_t packet_queue_capacity = 128; std::size_t frame_queue_capacity = 16; CPCodecID codec_id = CPCodecID::Unknow; std::string codec_name; std::vector slave_request_command{}; std::chrono::milliseconds slave_request_interval = 200ms; }; class CPStreamCore { public: using FrameCallback = std::function; explicit CPStreamCore(CPStreamConfig config = {}); ~CPStreamCore(); CPStreamCore(const CPStreamCore&) = delete; CPStreamCore& operator=(const CPStreamCore&) = delete; bool open(const CPStreamConfig& config); bool open(); bool reopen(const CPStreamConfig& config); void close(); bool start(); void stop(); [[nodiscard]] bool is_open() const noexcept; [[nodiscard]] bool is_running() const noexcept; bool send(const std::vector& data); bool send(const std::uint8_t* data, std::size_t size); std::optional try_pop_frame(); bool wait_for_frame(DecodedFrame& frame, std::chrono::milliseconds timeout); void clear_frames(); void set_frame_queue_capacity(std::size_t capacity); void set_frame_callback(FrameCallback callback); [[nodiscard]] CPStreamConfig config() const; [[nodiscard]] std::string last_error() const; static std::vector list_available_ports(); private: struct Impl; std::unique_ptr impl_; }; } // namespace ffmsep