diff --git a/demos/applications/ch9329_nunchuck_mouse.cpp b/demos/applications/ch9329_nunchuck_mouse.cpp index 8b64ce4..3a29959 100644 --- a/demos/applications/ch9329_nunchuck_mouse.cpp +++ b/demos/applications/ch9329_nunchuck_mouse.cpp @@ -32,8 +32,7 @@ void application(resource_list& p_map) auto& i2c = *p_map.i2c.value(); hal::input::nunchuck nunchuck(i2c); - hal::input::ch9329 usb_control(uart3); - hal::input::ch9329::keyboard_general kb_control; + hal::input::ch9329 usb_control(uart3, clock); hal::input::ch9329::mouse_relative rel_mouse_control; hal::print(console, "Demo Application Starting...\n\n"); diff --git a/include/libhal-input/ch9329.hpp b/include/libhal-input/ch9329.hpp index 0079678..f051f87 100644 --- a/include/libhal-input/ch9329.hpp +++ b/include/libhal-input/ch9329.hpp @@ -14,26 +14,340 @@ #pragma once +#include #include #include +#include +#include #include +#include +#include #include namespace hal::input { -/** - * @brief Driver for CH9329 UART to USB - * - */ constexpr auto mouse_abs_data_size = 7; constexpr auto mouse_rel_data_size = 5; constexpr auto kb_media_data_size = 4; constexpr auto kb_acpi_data_size = 2; constexpr auto kb_general_data_size = 8; +constexpr auto parameter_data_size = 50; +constexpr auto filter_chars_length = 4; +constexpr auto usb_string_descriptor_max_length = 23; +/** + * @brief Driver for CH9329 UART to USB + * + */ class ch9329 { public: + /** + * @brief Holds information about the chip from the cmd_get_info command + * + */ + struct chip_info + { + /// chip version, 0x30 indicates version 1.0 + hal::byte version; + /// usb enumeration status of the chip + bool enumeration_status; + /// status of num lock (0 means off, 1 is on) + bool num_lock; + /// status of caps lock (0 means off, 1 is on) + bool caps_lock; + /// status of scroll lock (0 means off, 1 is on) + bool scroll_lock; + }; + + /** + * @brief Holds data used to get and set usb string descriptors + * + */ + struct usb_string_descriptor + { + auto full_span() + { + return std::span(buffer); + } + auto received_data() + { + return std::span(buffer).first(length); + } + std::array buffer{}; + std::size_t length = 0; + }; + + /** + * @brief Holds data and functions related to getting and setting parameter + * configurations on the chip + * + */ + class ch9329_parameters + { + public: + /** + * @brief Construct a new ch9329 parameters object with all 0x00 data bytes + * + */ + ch9329_parameters(); + /** + * @brief Construct a new ch9329 parameters object with an array of bytes + * containing parameters + * + * @param p_config_bytes array holding parameter settings in bytes + */ + ch9329_parameters( + std::array p_config_bytes); + + /** + * @brief Set the array containing parameter bytes + * + * @param p_config_bytes bytes containing parameters + * @return ch9329_parameters& + */ + ch9329_parameters& set_config_bytes( + std::array p_config_bytes); + /** + * @brief Set the chip working mode. + * + * @param p_working_mode working_mode enum representing which working mode + * to use + * @return ch9329_parameters& + */ + ch9329_parameters& set_chip_working_mode(working_mode p_working_mode); + /** + * @brief Set the serial communication mode + * + * @param p_communication_mode communication_mode enum representing which + * communication mode to use + * @return ch9329_parameters& + */ + ch9329_parameters& set_serial_communication_mode( + communication_mode p_communication_mode); + /** + * @brief Set the serial mode baud rate + * + * @param p_baud baud rate to set the chip to use + * @return ch9329_parameters& + */ + ch9329_parameters& set_serial_mode_baud_rate(std::uint32_t p_baud); + /** + * @brief Set the serial address + * + * @param p_serial serial address of chip + * @return ch9329_parameters& + */ + ch9329_parameters& set_serial_address(hal::byte p_serial); + /** + * @brief Set the serial mode packet interval + * + * @param p_packet_interval max time in ms to wait between bytes before + * ending packet + * @return ch9329_parameters& + */ + ch9329_parameters& set_serial_mode_packet_interval( + std::uint16_t p_packet_interval); + /** + * @brief Set the vendor id + * + * @param p_vid 2 bytes representing the vendor id of the chip + * @return ch9329_parameters& + */ + ch9329_parameters& set_vendor_id(std::uint16_t p_vid); + /** + * @brief Set the product id + * + * @param p_pid 2 bytes representing the product id of the chip + * @return ch9329_parameters& + */ + ch9329_parameters& set_product_id(std::uint16_t p_pid); + /** + * @brief Set the ascii mode keyboard upload interval + * + * @param p_upload_interval time to wait in ms between sending packets in + * ascii mode + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_upload_interval( + std::uint16_t p_upload_interval); + /** + * @brief Set the ascii mode keyboard release delay + * + * @param p_release_delay time to wait in ms before sending packet to + * release keys pressed in ascii mode ascii mode + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_release_delay( + std::uint16_t p_release_delay); + /** + * @brief Set the ascii mode keyboard auto enter + * + * @param p_auto_enter auto send enter after end of package in ascii mode + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_auto_enter(bool p_auto_enter); + /** + * @brief Set the ascii mode keyboard carriage return 1 + * + * @param p_carriage_return + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_carriage_return_1( + std::uint32_t p_carriage_return); + /** + * @brief Set the ascii mode keyboard carriage return 2 + * + * @param p_carriage_return + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_carriage_return_2( + std::uint32_t p_carriage_return); + /** + * @brief Set the keyboard start filter characters + * + * @param p_start_filters start filter characters + * @return ch9329_parameters& + */ + ch9329_parameters& set_kb_start_filter_chars( + std::array p_start_filters); + /** + * @brief Set the keyboard end filter characters + * + * @param p_end_filters end filter characters + * @return ch9329_parameters& + */ + ch9329_parameters& set_kb_end_filter_chars( + std::array p_end_filters); + /** + * @brief Enable or disable custom usb string descriptors + * + * @param p_descriptor custom_descriptor enum representing which descriptor + * to change + * @param p_enable allow custom string descriptor + * @return ch9329_parameters& + */ + ch9329_parameters& set_usb_string_enable(custom_descriptor p_descriptor, + bool p_enable); + /** + * @brief Set the ascii mode keyboard fast upload mode + * + * @param p_fast_upload send all characters before sending release keys + * packets + * @return ch9329_parameters& + */ + ch9329_parameters& set_ascii_mode_kb_fast_upload_mode(bool p_fast_upload); + + /** + * @brief Get the chip working mode + * + * @return working_mode + */ + working_mode get_chip_working_mode(); + /** + * @brief Get the serial communication mode + * + * @return communication_mode + */ + communication_mode get_serial_communication_mode(); + /** + * @brief Get the serial address + * + * @return hal::byte + */ + hal::byte get_serial_address(); + /** + * @brief Get the serial mode baud rate + * + * @return std::uint32_t + */ + std::uint32_t get_serial_mode_baud_rate(); + /** + * @brief Get the serial mode packet interval + * + * @return std::uint16_t + */ + std::uint16_t get_serial_mode_packet_interval(); + /** + * @brief Get the vendor id + * + * @return std::uint16_t + */ + std::uint16_t get_vendor_id(); + /** + * @brief Get the product id + * + * @return std::uint16_t + */ + std::uint16_t get_product_id(); + /** + * @brief Get the ascii mode keyboard upload interval + * + * @return std::uint16_t + */ + std::uint16_t get_ascii_mode_kb_upload_interval(); + /** + * @brief Get the ascii mode keyboard release delay + * + * @return std::uint16_t + */ + std::uint16_t get_ascii_mode_kb_release_delay(); + /** + * @brief Get the ascii mode keyboard auto enter flag + * + * @return bool + */ + bool get_ascii_mode_kb_auto_enter(); + /** + * @brief Get the ascii mode keyboard carriage return 1 + * + * @return std::uint32_t + */ + std::uint32_t get_ascii_mode_kb_carriage_return_1(); + /** + * @brief Get the ascii mode keyboard carriage return 2 + * + * @return std::uint32_t + */ + std::uint32_t get_ascii_mode_kb_carriage_return_2(); + /** + * @brief Get the keyboard start filter characters + * + * @return std::array + */ + std::array get_kb_start_filter_chars(); + /** + * @brief Get the keyboard end filter characters + * + * @return std::array + */ + std::array get_kb_end_filter_chars(); + /** + * @brief Get the usb string enable flag + * + * @return bool + */ + bool get_usb_string_enable(custom_descriptor p_descriptor); + /** + * @brief Get the ascii mode keyboard fast upload mode + * + * @return hal::byte + */ + bool get_ascii_mode_kb_fast_upload_mode(); + /** + * @brief Get the config bytes array + * + * @return auto const& + */ + auto const& get_config_bytes() const + { + return m_config_bytes; + } + + private: + std::array m_config_bytes = {}; + }; + /** * @brief Holds data and functions related to using mouse absolute position * commands @@ -346,7 +660,7 @@ class ch9329 * * @param p_uart uart used to communicate with CH9329 */ - ch9329(hal::serial& p_uart); + ch9329(hal::serial& p_uart, hal::steady_clock& p_clock); /** * @brief Send mouse absolute position command * @@ -377,6 +691,76 @@ class ch9329 * @param p_data keyboard general object containing command bytes */ void send(keyboard_general const& p_data); + + /** + * @brief Set the parameters configuration of the chip + * + * @param p_data object containing parameters to change + * @return hal::byte status byte returned from chip + */ + hal::byte set_parameters(ch9329_parameters const& p_data, + hal::function_ref p_timeout); + /** + * @brief Get the current parameters configuration from the chip + * + * @return ch9329_parameters contains parameters and the response bytes + */ + ch9329_parameters get_parameters( + hal::function_ref p_timeout); + /** + * @brief Get info about the chip + * + * @return chip_info contains basic information about the chip + */ + chip_info get_info(hal::function_ref p_timeout); + /** + * @brief Get the manufacturer usb string descriptor on the chip + * + * @return usb_string_descriptor contains buffer and trimmed data + */ + usb_string_descriptor get_manufacturer_descriptor( + hal::function_ref p_timeout); + /** + * @brief Get the product usb string descriptor on the chip + * + * @return usb_string_descriptor contains buffer and trimmed data + */ + usb_string_descriptor get_product_descriptor( + hal::function_ref p_timeout); + /** + * @brief Get the serial number usb string descriptor on the chip + * + * @return usb_string_descriptor contains buffer and trimmed data + */ + usb_string_descriptor get_serial_number_descriptor( + hal::function_ref p_timeout); + /** + * @brief Set the manufacturer usb string descriptor + * + * @param p_string string to use as descriptor + * @return hal::byte status byte returned from the chip + */ + hal::byte set_manufacturer_descriptor(std::string_view p_string); + /** + * @brief Set the product usb string descriptor + * + * @param p_string string to use as descriptor + * @return hal::byte status byte returned from the chip + */ + hal::byte set_product_descriptor(std::string_view p_string); + /** + * @brief Set the serial number usb string descriptor + * + * @param p_string string to use as descriptor + * @return hal::byte status byte returned from the chip + */ + hal::byte set_serial_number_descriptor(std::string_view p_string); + /** + * @brief Restore all settings to factory default + * + * @return hal::byte status byte returned from the chip + */ + hal::byte restore_factory_default_settings(); /** * @brief Reset the chip using the cmd_reset command * diff --git a/include/libhal-input/ch9329_parameter_constants.hpp b/include/libhal-input/ch9329_parameter_constants.hpp new file mode 100644 index 0000000..9fe85a2 --- /dev/null +++ b/include/libhal-input/ch9329_parameter_constants.hpp @@ -0,0 +1,66 @@ +// Copyright 2024 Khalil Estell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +enum class working_mode : hal::byte +{ + // software mode keyboard (normal & multimedia) and mouse + software_keyboard_and_mouse = 0x00, + // software mode keyboard (normal) only + software_keyboard_only = 0x01, + // software mode mouse only + software_mouse_only = 0x02, + // software mode HID mode + software_hid_mode = 0x03, + // hardware mode keyboard (normal & multimedia) and mouse + hardware_keyboard_and_mouse = 0x80, + // hardware mode keyboard (normal) only + hardware_keyboard_only = 0x81, + // hardware mode mouse only + hardware_mouse_only = 0x82, + // hardware mode HID mode + hardware_hid_mode = 0x83 +}; + +enum class communication_mode : hal::byte +{ + // software set protocol transmission mode + software_protocol_mode = 0x00, + // software set ascii mode + software_ascii_mode = 0x01, + // software set transparent mode + software_transparent_mode = 0x02, + // hardware set protocol transmission mode + hardware_protocol_mode = 0x80, + // hardware set ascii mode + hardware_ascii_mode = 0x81, + // hardware set transparent mode + hardware_transparent_mode = 0x82 +}; + +enum class custom_descriptor : std::uint8_t +{ + serial_number = 0, + product_string = 1, + vendor_string = 2, + usb_string = 7 +}; + +enum class lock_status : std::uint8_t +{ + num_lock = 0, + caps_lock = 1, + scroll_lock = 2 +}; diff --git a/src/ch9329.cpp b/src/ch9329.cpp index ee99201..03ee3d9 100644 --- a/src/ch9329.cpp +++ b/src/ch9329.cpp @@ -16,6 +16,9 @@ #include #include +#include +#include +#include #include #include @@ -25,6 +28,7 @@ #include #include #include +#include namespace hal::input { @@ -32,17 +36,66 @@ constexpr hal::byte header_byte_1 = 0x57; constexpr hal::byte header_byte_2 = 0xAB; constexpr hal::byte address_byte = 0x00; +constexpr hal::byte cmd_get_info = 0x01; +constexpr hal::byte cmd_get_usb_string = 0x0A; +constexpr hal::byte cmd_set_usb_string = 0x0B; +constexpr hal::byte cmd_restore_factory_default_settings = 0x0C; constexpr hal::byte cmd_reset = 0x0F; constexpr hal::byte cmd_send_kb_general_data = 0x02; constexpr hal::byte cmd_send_kb_media_data = 0x03; constexpr hal::byte cmd_send_ms_abs_data = 0x04; constexpr hal::byte cmd_send_ms_rel_data = 0x05; +constexpr hal::byte cmd_get_para_cfg = 0x08; +constexpr hal::byte cmd_set_para_cfg = 0x09; constexpr auto header_frame_size = 5; - -ch9329::ch9329(hal::serial& p_uart) +constexpr auto info_response_length = 14; +constexpr auto response_length = 7; +constexpr auto response_byte = 5; +constexpr auto response_header_length = 5; +constexpr auto check_sum_read_length = 1; +constexpr auto string_header_length = 2; +constexpr auto parameters_length = 50; + +constexpr std::array standard_baud_rates = { 9600, + 19200, + 38400, + 57600, + 115200 }; + +ch9329::ch9329(hal::serial& p_uart, hal::steady_clock& p_clock) : m_uart(&p_uart) { + using namespace std::chrono_literals; + auto wait_time = hal::create_timeout(p_clock, 10ms); + for (auto baud : standard_baud_rates) { + try { + m_uart->configure({ .baud_rate = baud }); + auto response = get_info(wait_time); + if (response.version < 0x30) { + break; + } + } catch (timed_out) { + // what do here? + throw; + } + } +} + +ch9329::ch9329_parameters::ch9329_parameters( + std::array p_config_bytes) + : m_config_bytes(p_config_bytes){}; + +ch9329::ch9329_parameters::ch9329_parameters() +{ + // these are the default parameters + m_config_bytes = { + 0x80, 0x80, 0x00, 0x00, 0x00, 0x25, 0x80, 0x08, 0x00, 0x00, + 0x03, 0x86, 0x1A, 0x29, 0xE1, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; } ch9329::mouse_absolute::mouse_absolute(std::uint16_t p_screen_width, @@ -85,6 +138,10 @@ hal::byte get_size_byte(hal::byte p_command) return 0x07; case cmd_send_ms_rel_data: return 0x05; + case cmd_get_usb_string: + return 0x01; + case cmd_set_para_cfg: + return 0x32; } return 0x00; } @@ -161,14 +218,145 @@ void ch9329::send(keyboard_acpi const& p_data) send_command_with_bytes(bytes, cmd_send_kb_media_data, *m_uart, 2); } +ch9329::chip_info ch9329::get_info( + hal::function_ref p_timeout = hal::never_timeout()) +{ + std::array response{}; + send_start_bytes(*m_uart, cmd_get_info); + hal::print(*m_uart, std::to_array({ (hal::byte)0x03 })); // sum byte + hal::read(*m_uart, response, p_timeout); + chip_info info = {}; + info.version = response[5]; + info.enumeration_status = response[6]; + info.num_lock = response[7] & (1 << hal::value(lock_status::num_lock)); + info.caps_lock = response[7] & (1 << hal::value(lock_status::caps_lock)); + info.scroll_lock = response[7] & (1 << hal::value(lock_status::scroll_lock)); + return info; +} + +ch9329::usb_string_descriptor get_usb_string_descriptor( + serial& p_serial, + hal::byte p_string_type, + hal::function_ref p_timeout) +{ + ch9329::usb_string_descriptor str; + auto bytes = std::to_array({ p_string_type }); + send_command_with_bytes(bytes, cmd_get_usb_string, p_serial); + std::array header_bytes; + hal::read(p_serial, header_bytes, p_timeout); + str.length = header_bytes.back(); + hal::read(p_serial, str.received_data(), p_timeout); + std::array check_sum; + hal::read(p_serial, check_sum, p_timeout); + return str; +} + +hal::byte set_usb_string_descriptor(serial& p_serial, + hal::byte p_string_type, + std::string_view p_string) +{ + uint8_t string_length = p_string.length(); + auto string_header = std::to_array({ p_string_type, string_length }); + send_start_bytes( + p_serial, cmd_set_usb_string, string_length + string_header_length); + hal::print(p_serial, string_header); + hal::print(p_serial, p_string); + // get the sum up to the end of the string header + auto sum_byte = calculate_sum(string_header, cmd_set_usb_string); + // add string header bytes to sum + sum_byte += (string_length + string_header_length); + // add chars in string to sum + for (hal::byte byte : p_string) { + sum_byte += byte; + } + // send sum byte + hal::print(p_serial, std::to_array({ sum_byte })); + std::array response; + hal::read(p_serial, response, hal::never_timeout()); + return response[response_byte]; +} + +ch9329::usb_string_descriptor ch9329::get_manufacturer_descriptor( + hal::function_ref p_timeout = hal::never_timeout()) +{ + return get_usb_string_descriptor(*m_uart, 0x00, p_timeout); +} + +ch9329::usb_string_descriptor ch9329::get_product_descriptor( + hal::function_ref p_timeout = hal::never_timeout()) +{ + return get_usb_string_descriptor(*m_uart, 0x01, p_timeout); +} + +ch9329::usb_string_descriptor ch9329::get_serial_number_descriptor( + hal::function_ref p_timeout = hal::never_timeout()) +{ + return get_usb_string_descriptor(*m_uart, 0x02, p_timeout); +} + +hal::byte ch9329::set_manufacturer_descriptor(std::string_view p_string) +{ + return set_usb_string_descriptor(*m_uart, 0x00, p_string); +} + +hal::byte ch9329::set_product_descriptor(std::string_view p_string) +{ + return set_usb_string_descriptor(*m_uart, 0x01, p_string); +} + +hal::byte ch9329::set_serial_number_descriptor(std::string_view p_string) +{ + return set_usb_string_descriptor(*m_uart, 0x02, p_string); +} + +hal::byte ch9329::restore_factory_default_settings() +{ + send_start_bytes(*m_uart, cmd_restore_factory_default_settings); + auto sum_byte = calculate_sum({}, cmd_restore_factory_default_settings); + hal::print(*m_uart, std::to_array({ sum_byte })); + std::array response; + hal::read(*m_uart, response, hal::never_timeout()); + return response[response_byte]; +} + hal::byte ch9329::reset() { send_start_bytes(*m_uart, cmd_reset); auto sum_byte = calculate_sum({}, cmd_reset); hal::print(*m_uart, std::to_array({ sum_byte })); - std::array response; + std::array response; hal::read(*m_uart, response, hal::never_timeout()); - return response[5]; + return response[response_byte]; +} + +ch9329::ch9329_parameters ch9329::get_parameters( + hal::function_ref p_timeout = hal::never_timeout()) +{ + send_start_bytes(*m_uart, cmd_get_para_cfg); + auto sum_byte = calculate_sum({}, cmd_get_para_cfg); + hal::print(*m_uart, std::to_array({ sum_byte })); + std::array response_header; + std::array response; + std::array response_sum; + + hal::read(*m_uart, response_header, p_timeout); + hal::read(*m_uart, response, p_timeout); + hal::read(*m_uart, response_sum, p_timeout); + + ch9329_parameters params(response); + + return params; +} + +hal::byte ch9329::set_parameters( + ch9329_parameters const& p_parameters, + hal::function_ref p_timeout = hal::never_timeout()) +{ + auto bytes = p_parameters.get_config_bytes(); + send_command_with_bytes(bytes, cmd_set_para_cfg, *m_uart); + std::array response; + hal::read(*m_uart, response, p_timeout); + return response[response_byte]; } // mouse absolute functions @@ -357,4 +545,230 @@ ch9329::keyboard_general& ch9329::keyboard_general::release_all_keys() m_data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; return *this; } + +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_config_bytes( + std::array p_config_bytes) +{ + m_config_bytes = p_config_bytes; + return *this; +}; + +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_chip_working_mode( + working_mode p_working_mode) +{ + m_config_bytes[0] = static_cast(p_working_mode); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_serial_communication_mode( + communication_mode p_communication_mode) +{ + m_config_bytes[1] = static_cast(p_communication_mode); + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_serial_address( + hal::byte p_serial) +{ + m_config_bytes[2] = p_serial; + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_serial_mode_baud_rate( + std::uint32_t p_baud) +{ + m_config_bytes[3] = static_cast(p_baud >> 24); + m_config_bytes[4] = static_cast(p_baud >> 16); + m_config_bytes[5] = static_cast(p_baud >> 8); + m_config_bytes[6] = static_cast(p_baud); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_serial_mode_packet_interval( + std::uint16_t p_packet_interval) +{ + m_config_bytes[9] = static_cast(p_packet_interval >> 8); + m_config_bytes[10] = static_cast(p_packet_interval); + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_vendor_id( + std::uint16_t p_vid) +{ + m_config_bytes[11] = static_cast(p_vid >> 8); + m_config_bytes[12] = static_cast(p_vid); + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_product_id( + std::uint16_t p_id) +{ + m_config_bytes[13] = static_cast(p_id >> 8); + m_config_bytes[14] = static_cast(p_id); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_upload_interval( + std::uint16_t p_upload_interval) +{ + m_config_bytes[15] = static_cast(p_upload_interval >> 8); + m_config_bytes[16] = static_cast(p_upload_interval); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_release_delay( + std::uint16_t p_release_dealy) +{ + m_config_bytes[17] = static_cast(p_release_dealy >> 8); + m_config_bytes[18] = static_cast(p_release_dealy); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_auto_enter(bool p_auto_enter) +{ + m_config_bytes[19] = + static_cast(p_auto_enter); // TODO: does this work? + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_carriage_return_1( + std::uint32_t p_carriage_return) +{ + m_config_bytes[20] = static_cast(p_carriage_return >> 24); + m_config_bytes[21] = static_cast(p_carriage_return >> 16); + m_config_bytes[22] = static_cast(p_carriage_return >> 8); + m_config_bytes[23] = static_cast(p_carriage_return); + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_carriage_return_2( + std::uint32_t p_carriage_return) +{ + m_config_bytes[24] = static_cast(p_carriage_return >> 24); + m_config_bytes[25] = static_cast(p_carriage_return >> 16); + m_config_bytes[26] = static_cast(p_carriage_return >> 8); + m_config_bytes[27] = static_cast(p_carriage_return); + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_kb_start_filter_chars( + std::array p_start_filters) +{ + m_config_bytes[28] = p_start_filters[0]; + m_config_bytes[29] = p_start_filters[1]; + m_config_bytes[30] = p_start_filters[2]; + m_config_bytes[31] = p_start_filters[3]; + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_kb_end_filter_chars( + std::array p_end_filters) +{ + m_config_bytes[32] = p_end_filters[0]; + m_config_bytes[33] = p_end_filters[1]; + m_config_bytes[34] = p_end_filters[2]; + m_config_bytes[35] = p_end_filters[3]; + return *this; +}; +ch9329::ch9329_parameters& ch9329::ch9329_parameters::set_usb_string_enable( + custom_descriptor p_descriptor, + bool p_enable) +{ + if (p_enable) { + hal::byte mask = 1 << hal::value(p_descriptor); + m_config_bytes[36] = m_config_bytes[36] | mask; + } else { + hal::byte mask = ~(1 << hal::value(p_descriptor)); + m_config_bytes[36] = m_config_bytes[36] & mask; + } + return *this; +}; +ch9329::ch9329_parameters& +ch9329::ch9329_parameters::set_ascii_mode_kb_fast_upload_mode( + bool p_fast_upload) +{ + m_config_bytes[37] = static_cast(p_fast_upload); + return *this; +}; +working_mode ch9329::ch9329_parameters::get_chip_working_mode() +{ + return static_cast(m_config_bytes[0]); +}; +communication_mode ch9329::ch9329_parameters::get_serial_communication_mode() +{ + return static_cast(m_config_bytes[1]); +}; +hal::byte ch9329::ch9329_parameters::get_serial_address() +{ + return m_config_bytes[2]; +}; +std::uint32_t ch9329::ch9329_parameters::get_serial_mode_baud_rate() +{ + std::uint32_t baud = m_config_bytes[3]; + baud = (baud << 8) | m_config_bytes[4]; + baud = (baud << 8) | m_config_bytes[5]; + baud = (baud << 8) | m_config_bytes[6]; + return baud; +}; +std::uint16_t ch9329::ch9329_parameters::get_serial_mode_packet_interval() +{ + return static_cast((m_config_bytes[9] << 8) | m_config_bytes[10]); +}; +std::uint16_t ch9329::ch9329_parameters::get_vendor_id() +{ + return static_cast((m_config_bytes[11] << 8) | m_config_bytes[12]); +}; +std::uint16_t ch9329::ch9329_parameters::get_product_id() +{ + return static_cast((m_config_bytes[13] << 8) | m_config_bytes[14]); +}; +std::uint16_t ch9329::ch9329_parameters::get_ascii_mode_kb_upload_interval() +{ + return static_cast((m_config_bytes[15] << 8) | m_config_bytes[16]); +}; +std::uint16_t ch9329::ch9329_parameters::get_ascii_mode_kb_release_delay() +{ + return static_cast((m_config_bytes[17] << 8) | m_config_bytes[18]); +}; +bool ch9329::ch9329_parameters::get_ascii_mode_kb_auto_enter() +{ + return static_cast(m_config_bytes[19]); +}; +std::uint32_t ch9329::ch9329_parameters::get_ascii_mode_kb_carriage_return_1() +{ + std::uint32_t carriage_ret_1 = m_config_bytes[20]; + carriage_ret_1 = (carriage_ret_1 << 8) | m_config_bytes[21]; + carriage_ret_1 = (carriage_ret_1 << 8) | m_config_bytes[22]; + carriage_ret_1 = (carriage_ret_1 << 8) | m_config_bytes[23]; + return carriage_ret_1; +}; +std::uint32_t ch9329::ch9329_parameters::get_ascii_mode_kb_carriage_return_2() +{ + std::uint32_t carriage_ret_2 = m_config_bytes[24]; + carriage_ret_2 = (carriage_ret_2 << 8) | m_config_bytes[25]; + carriage_ret_2 = (carriage_ret_2 << 8) | m_config_bytes[26]; + carriage_ret_2 = (carriage_ret_2 << 8) | m_config_bytes[27]; + return carriage_ret_2; +}; +std::array ch9329::ch9329_parameters::get_kb_start_filter_chars() +{ + std::array start_filters = { m_config_bytes[28], + m_config_bytes[29], + m_config_bytes[30], + m_config_bytes[31] }; + return start_filters; +}; +std::array ch9329::ch9329_parameters::get_kb_end_filter_chars() +{ + std::array end_filters = { m_config_bytes[32], + m_config_bytes[33], + m_config_bytes[34], + m_config_bytes[35] }; + return end_filters; +}; +bool ch9329::ch9329_parameters::get_usb_string_enable( + custom_descriptor p_descriptor) +{ + hal::byte mask = 1 << hal::value(p_descriptor); + hal::byte status = (m_config_bytes[36] | mask) >> hal::value(p_descriptor); + return static_cast(status); +}; +bool ch9329::ch9329_parameters::get_ascii_mode_kb_fast_upload_mode() +{ + return static_cast(m_config_bytes[37]); +}; } // namespace hal::input