/** * @file stmdsp.hpp * @brief Interface for communication with stmdsp device over serial. * * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. * If not, see . */ #ifndef STMDSP_HPP_ #define STMDSP_HPP_ #include #include #include #include #include #include #include namespace stmdsp { /** * The largest possible size of an ADC or DAC sample buffer, as a sample count. * Maximum byte size would be `SAMPLES_MAX * sizeof(XXXsample_t)`. */ constexpr unsigned int SAMPLES_MAX = 4096; /** * ADC samples on all platforms are stored as 16-bit unsigned integers. */ using adcsample_t = uint16_t; /** * DAC samples on all platforms are stored as 16-bit unsigned integers. */ using dacsample_t = uint16_t; /** * List of all available platforms. * Note that some platforms in this list may not have complete support. */ enum class platform { Unknown, H7, /* Some feature support */ L4, /* Complete feature support */ G4 /* Unsupported, but planned */ }; /** * Run status states, valued to match what the stmdsp firmware reports. */ enum class RunStatus : char { Idle = '1', /* Device ready for commands or execution. */ Running, /* Device currently executing its algorithm. */ Recovering /* Device recovering from fault caused by algorithm. */ }; /** * Error messages that are reported by the firmware. */ enum class Error : char { None = 0, BadParam, /* An invalid parameter was passed for a command. */ BadParamSize, /* An invaild param. size was given for a command. */ BadUserCodeLoad, /* Device failed to load the given algorithm. */ BadUserCodeSize, /* The given algorithm is too large for the device. */ NotIdle, /* An idle-only command was received while not Idle. */ ConversionAborted, /* A conversion was aborted due to a fault. */ NotRunning, /* A running-only command was received while not Running. */ GUIDisconnect = 100 /* The GUI lost connection with the device. */ }; /** * Provides functionality to scan the system for stmdsp devices. * A list of devices is returned, though the GUI only interacts with one * device at a time. */ class scanner { public: /** * Scans for connected devices, returning a list of ports with * connected stmdsp devices. */ const std::forward_list& scan(); /** * Retrieves the results of the last scan(). */ const std::forward_list& devices() const noexcept { return m_available_devices; } private: constexpr static const char *STMDSP_USB_ID = #ifndef STMDSP_WIN32 "USB VID:PID=0483:5740"; #else "USB\\VID_0483&PID_5740"; #endif std::forward_list m_available_devices; }; class device { public: device(const std::string& file); ~device(); bool connected(); void disconnect(); auto get_platform() const { return m_platform; } void continuous_set_buffer_size(unsigned int size); unsigned int get_buffer_size() const { return m_buffer_size; } void set_sample_rate(unsigned int rate); unsigned int get_sample_rate(); void continuous_start(); void continuous_stop(); void measurement_start(); uint32_t measurement_read(); std::vector continuous_read(); std::vector continuous_read_input(); bool siggen_upload(dacsample_t *buffer, unsigned int size); void siggen_start(); void siggen_stop(); bool is_siggening() const { return m_is_siggening; } bool is_running() const { return m_is_running; } // buffer is ELF binary void upload_filter(unsigned char *buffer, size_t size); void unload_filter(); std::pair get_status(); private: std::unique_ptr m_serial; platform m_platform = platform::Unknown; unsigned int m_buffer_size = SAMPLES_MAX; unsigned int m_sample_rate = 0; bool m_is_siggening = false; bool m_is_running = false; bool m_disconnect_error_flag = false; std::mutex m_lock; bool try_command(std::basic_string data); bool try_read(std::basic_string cmd, uint8_t *dest, unsigned int dest_size); void handle_disconnect(); }; } #endif // STMDSP_HPP_