initial commit

This commit is contained in:
huangweifeng
2026-10-22 09:23:54 +08:00
commit 63f557a39f
4448 changed files with 584487 additions and 0 deletions
+92
View File
@@ -0,0 +1,92 @@
#ifndef GAMEPAD_H
#define GAMEPAD_H
#include <functional>
#include <thread>
#include <mutex>
#include <atomic>
#include <vector>
#include "gamepad_keys.h"
#include <iostream>
/**
* @brief A template class for a generic Gamepad.
*
* This class serves as a generic gamepad template. It can be specialized for specific gamepad types.
*
* @tparam KeysType The type of keys for the gamepad (e.g., XboxKeys, PlayStationKeys).
*/
template <typename KeysType>
class Gamepad {
public:
std::vector<std::string> button_status_;
/**
* @brief Constructor for the Gamepad class.
*
* Initializes the gamepad with the specified UDP port for data reception.
*
* @param port The UDP port to use for receiving gamepad data.
*/
Gamepad(int port = kDefaultPort);
/**
* @brief Destructor for the Gamepad class.
*
* This destructor stops the data thread to clean up resources when the gamepad instance is destroyed.
*/
virtual ~Gamepad(){
StopDataThread();
}
/**
* @brief Starts the data thread for simulating gamepad data.
*/
void StartDataThread();
/**
* @brief Stops the data thread.
*/
void StopDataThread();
/**
* @brief Gets the gamepad keys.
* @return The current gamepad keys.
*/
KeysType& GetKeys();
/**
* @brief Sets a callback function to be called on each data update.
* @param callback The callback function that takes an update count as an argument.
*/
void SetUpdateCallback(const std::function<void(uint32_t)>& callback);
/**
* @brief Calculate the CRC-16 checksum for a given data buffer.
*
* @param data Pointer to the data buffer.
* @param length Length of the data buffer.
* @return The CRC-16 checksum of the data.
*/
uint16_t CalculateCrc16(const uint8_t* data, size_t length);
std::function<void(uint32_t)> updateCallback_; ///< Callback function for data updates.
protected:
std::thread data_thread_; ///< Thread for generating simulated data.
std::atomic<bool> stop_thread_; ///< Flag to signal the data thread to stop.
mutable std::mutex mutex_; ///< Mutex for data access synchronization.
KeysType keys_; ///< Gamepad keys.
int port_; ///< The UDP port for data reception.
timespec start_time_; //receive timestamp start time
/**
* @brief Updates the gamepad data buffer and keys.
*
* @param buffer The data buffer to be updated.
* @param keys The keys to be updated.
* @return True if the data is valid and updated, false otherwise.
*/
virtual bool UpdateData(std::vector<uint8_t>& buffer, KeysType& keys) = 0;
};
#endif
+189
View File
@@ -0,0 +1,189 @@
#ifndef GAMEPAD_KEYS_H
#define GAMEPAD_KEYS_H
/**
* @file gamepad_keys.h
* @brief Defines structures and constants related to gamepad keys and data.
*/
#include <cstddef>
#include <cstdint>
#include <cmath>
#include <array>
/** @brief Size of the header in bytes. */
const size_t kHeaderSize = 2;
/** @brief Total number of channels for gamepad keys. */
const size_t kChannlSize = 16;
/** @brief Number of channels dedicated to axis values in the gamepad data. */
const size_t kAxisChannlSize = 4;
/** @brief Number of channels dedicated to axis buttons in the gamepad data. */
const size_t kAxisButtonSize = 2;
const size_t kSwitchKeysSize = 4;
/** @brief Maximum range of the joystick axis values. */
const uint16_t kJoystickRange = 1000;
/** @brief Default UDP port for gamepad data reception. */
const uint16_t kDefaultPort = 12121;
/** @brief Header bytes for identifying gamepad data. */
const unsigned char kHeader[kHeaderSize] = {0x55, 0x66};
const size_t kRetroidButtonSize = 10;
const size_t kSkydroidButtonSize = 8;
/** @brief Enumerates different types of gamepads. */
enum class GamepadType {
kRetroid = 1, /**< RETROID gamepad type. */
kSkydroid = 2,
};
/** @brief Enumerates the status of keys, whether pressed or released. */
enum class KeyStatus {
kReleased = 0, /**< Key is released. */
kPressed = 1, /**< Key is pressed. */
};
/**
* @brief Structure representing the keys of a Retroid gamepad.
*/
struct RetroidKeys {
double time_stamp;
union {
uint16_t value; /**< Union to represent the keys as a single value. */
struct {
uint8_t R1 : 1; /**< R1 button. */
uint8_t L1 : 1; /**< L1 button. */
uint8_t start : 1; /**< Start button. */
uint8_t select : 1; /**< Select button. */
uint8_t R2 : 1; /**< R2 button. */
uint8_t L2 : 1; /**< L2 button. */
uint8_t A : 1; /**< A button. */
uint8_t B : 1; /**< B button. */
uint8_t X : 1; /**< X button. */
uint8_t Y : 1; /**< Y button. */
uint8_t left : 1; /**< Left button on the directional pad. */
uint8_t right : 1; /**< Right button on the directional pad. */
uint8_t up : 1; /**< Up button on the directional pad. */
uint8_t down : 1; /**< Down button on the directional pad. */
uint8_t left_axis_button : 1; /**< Left analog stick button. */
uint8_t right_axis_button : 1; /**< Right analog stick button. */
};
};
union {
float axis_values[kAxisChannlSize]; /**< Array representing axis values. */
struct {
float left_axis_x; /**< X-axis value of the left analog stick. */
float left_axis_y; /**< Y-axis value of the left analog stick. */
float right_axis_x; /**< X-axis value of the right analog stick. */
float right_axis_y; /**< Y-axis value of the right analog stick. */
};
};
};
/**
* @brief Structure representing the keys of a Skydroid Gamepad.
*/
struct SkydroidKeys {
double time_stamp;
union {
uint8_t keys_value; /**< Union to represent the button as a single value. */
struct {
uint8_t C : 1; /**< C button. */
uint8_t right : 1; /**< right button. */
uint8_t D : 1; /**< D button. */
uint8_t E : 1; /**< E button. */
uint8_t F : 1; /**< F button. */
uint8_t reserved : 1; /**< reserved. */
uint8_t A : 1; /**< A button. */
uint8_t B : 1; /**< B button. */
};
};
union {
uint8_t switch_keys[kSwitchKeysSize]; /**< Array representing switch_keys values. */
struct {
uint8_t sw1 ; /**< switch_key1 */
uint8_t sw2 ; /**< switch_key2 */
uint8_t sw3 ; /**< switch_key3 */
uint8_t sw4 ; /**< switch_key4 */
};
};
union {
float axis_values[kAxisChannlSize]; /**< Array representing axis values. */
struct {
float left_axis_x; /**< X-axis value of the left analog stick. */
float left_axis_y; /**< Y-axis value of the left analog stick. */
float right_axis_x; /**< X-axis value of the right analog stick. */
float right_axis_y; /**< Y-axis value of the right analog stick. */
};
};
};
#pragma pack(1)
/**
* @brief Structure representing the complete gamepad data packet.
*/
struct RetroidGamepadData {
uint8_t stx[kHeaderSize]; /**< Start-of-text bytes for identifying the start of data. */
uint8_t ctrl; /**< Control byte for additional flags or information. */
uint16_t data_len; /**< Length of the data in the packet. */
uint16_t seq; /**< Sequence number for tracking packet order or identifying duplicates. */
uint8_t id; /**< Identifier for the type of gamepad. */
uint16_t crc16; /**< CRC-16 checksum for data integrity verification. */
union {
uint8_t data[kChannlSize * sizeof(uint16_t)]; /**< Array representing raw data channels. */
struct {
uint16_t buttons[kRetroidButtonSize]; /**< Array representing button values. */
int16_t left_axis_x; /**< X-axis value of the left analog stick. */
int16_t left_axis_y; /**< Y-axis value of the left analog stick. */
int16_t right_axis_x; /**< X-axis value of the right analog stick. */
int16_t right_axis_y; /**< Y-axis value of the right analog stick. */
uint16_t axis_buttons[kAxisButtonSize]; /**< Array representing axis button values. */
};
};
};
#pragma pack()
#pragma pack(1)
/**
* @brief Structure representing the complete Gamepad data packet.
*/
struct SkydroidGamepadData {
uint8_t stx[kHeaderSize]; /**< Start-of-text bytes for identifying the start of data. */
uint8_t ctrl; /**< Control byte for additional flags or information. */
uint16_t data_len; /**< Length of the data in the packet. */
uint16_t seq; /**< Sequence number for tracking packet order or identifying duplicates. */
uint8_t id; /**< Identifier for the type of Gamepad. */
uint16_t crc16; /**< CRC-16 checksum for data integrity verification. */
union {
uint8_t data[kChannlSize * sizeof(uint16_t)]; /**< Array representing raw data channels. */
struct {
int16_t right_axis_x; /**< X-axis value of the right analog stick. */
int16_t right_axis_y; /**< Y-axis value of the right analog stick. */
int16_t left_axis_y; /**< Y-axis value of the left analog stick. */
int16_t left_axis_x; /**< X-axis value of the left analog stick. */
uint16_t switch_keys[kSwitchKeysSize]; /**< Array representing switch_keys values. */
uint16_t buttons[kSkydroidButtonSize]; /**< Array representing button values. */
};
};
};
#pragma pack()
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef RETROID_GAMEPAD_H
#define RETROID_GAMEPAD_H
#include <iostream>
#include <ostream>
#include "gamepad.h"
/**
* @brief A specialized class for RETROID gamepad.
*
* This class specializes the generic Gamepad class for RETROID gamepad.
*/
class RetroidGamepad : public Gamepad<RetroidKeys> {
public:
/**
* @brief Constructor for the RetroidGamepad class.
*
* Initializes the Retroid gamepad with the specified UDP port for data reception.
*
* @param port The UDP port to use for receiving gamepad data.
*/
RetroidGamepad(int port = kDefaultPort);
// /**
// * @brief Overloaded output stream operator for RetroidGamepad.
// *
// * Allows printing RetroidGamepad information to an output stream.
// *
// * @param o The output stream.
// * @param is The RetroidGamepad object.
// * @return Reference to the output stream.
// */
// friend std::ostream& operator<<(std::ostream& o, RetroidGamepad& is);
protected:
/**
* @brief Updates the RETROID gamepad data buffer and keys.
*
* @param buffer The data buffer to be updated.
* @param keys The RETROID gamepad keys to be updated.
* @return True if the data is valid and updated, false otherwise.
*/
bool UpdateData(std::vector<uint8_t>& buffer, RetroidKeys& keys) override;
/**
* @brief Checks if the received data from the RETROID gamepad is valid.
*
* @param data The gamepad data to be validated.
* @return True if the data is valid, false otherwise.
*/
bool DataIsValid(const RetroidGamepadData& data);
};
#endif // RETROID_GAMEPAD_H
+54
View File
@@ -0,0 +1,54 @@
#ifndef SKYDROID_GAMEPAD_H
#define SKYDROID_GAMEPAD_H
#include <iostream>
#include <ostream>
#include "gamepad.h"
/**
* @brief A specialized class for Skydroid gamepad.
*
* This class specializes the generic Gamepad class for Skydroid gamepad.
*/
class SkydroidGamepad : public Gamepad<SkydroidKeys> {
public:
/**
* @brief Constructor for the SkydroidGamepad class.
*
* Initializes the Skydroid gamepad with the specified UDP port for data reception.
*
* @param port The UDP port to use for receiving gamepad data.
*/
SkydroidGamepad(int port = kDefaultPort);
// /**
// * @brief Overloaded output stream operator for SkydroidGamepad.
// *
// * Allows printing SkydroidGamepad information to an output stream.
// *
// * @param o The output stream.
// * @param is The SkydroidGamepad object.
// * @return Reference to the output stream.
// */
// friend std::ostream& operator<<(std::ostream& o, SkydroidGamepad& is);
protected:
/**
* @brief Updates the Skydroid gamepad data buffer and keys.
*
* @param buffer The data buffer to be updated.
* @param keys The Skydroid gamepad keys to be updated.
* @return True if the data is valid and updated, false otherwise.
*/
bool UpdateData(std::vector<uint8_t>& buffer, SkydroidKeys& keys) override;
/**
* @brief Checks if the received data from the Skydroid gamepad is valid.
*
* @param data The gamepad data to be validated.
* @return True if the data is valid, false otherwise.
*/
bool DataIsValid(const SkydroidGamepadData& data);
};
#endif // SKYDROID_GAMEPAD_H
+33
View File
@@ -0,0 +1,33 @@
#ifndef UDP_RECEIVER_H
#define UDP_RECEIVER_H
#include <vector>
#include <cstdint>
/**
* @brief The UdpReceiver class for receiving UDP data.
*/
class UdpReceiver {
public:
/**
* @brief Constructor for UdpReceiver.
* @param port The port to listen for UDP data.
*/
UdpReceiver(int port);
/**
* @brief Receive UDP data.
* @return A vector containing received data as uint8_t.
*/
std::vector<uint8_t> ReceiveData();
/**
* @brief Destructor for UdpReceiver.
*/
~UdpReceiver();
private:
int socket_fd_;
};
#endif