104 lines
3.1 KiB
C
104 lines
3.1 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <string>
|
||
|
|
||
|
#include "util/circular_buffer.h"
|
||
|
|
||
|
// convert big-endian to little-endian
|
||
|
#define acio_u16 _byteswap_ushort
|
||
|
#define acio_u32 _byteswap_ulong
|
||
|
|
||
|
namespace acioemu {
|
||
|
|
||
|
constexpr uint8_t ACIO_SOF = 0xAA;
|
||
|
constexpr uint8_t ACIO_ESCAPE = 0xFF;
|
||
|
constexpr uint8_t ACIO_BROADCAST = 0x70;
|
||
|
constexpr uint8_t ACIO_RESPONSE_FLAG = 0x80;
|
||
|
|
||
|
// general command codes
|
||
|
enum acio_cmd_codes {
|
||
|
ACIO_CMD_ASSIGN_ADDRS = 0x0001,
|
||
|
ACIO_CMD_GET_VERSION = 0x0002,
|
||
|
ACIO_CMD_STARTUP = 0x0003,
|
||
|
ACIO_CMD_KEEPALIVE = 0x0080,
|
||
|
ACIO_CMD_CLEAR = 0x0100,
|
||
|
};
|
||
|
|
||
|
// message structs
|
||
|
#pragma pack(push, 1)
|
||
|
struct VersionData {
|
||
|
uint32_t type;
|
||
|
uint8_t flag;
|
||
|
uint8_t ver_major;
|
||
|
uint8_t ver_minor;
|
||
|
uint8_t ver_rev;
|
||
|
char code[4];
|
||
|
char date[16];
|
||
|
char time[16];
|
||
|
};
|
||
|
|
||
|
struct MessageData {
|
||
|
uint8_t addr;
|
||
|
|
||
|
union {
|
||
|
struct {
|
||
|
uint16_t code;
|
||
|
uint8_t pid;
|
||
|
uint8_t data_size;
|
||
|
|
||
|
union {
|
||
|
uint8_t raw[0xFF];
|
||
|
uint8_t status;
|
||
|
VersionData data_version;
|
||
|
};
|
||
|
} cmd;
|
||
|
|
||
|
struct {
|
||
|
uint8_t data_size;
|
||
|
uint8_t raw[0xFF];
|
||
|
} broadcast;
|
||
|
};
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
// message sizes
|
||
|
constexpr size_t MSG_HEADER_SIZE = 5;
|
||
|
constexpr size_t MSG_VERSION_SIZE = sizeof(VersionData);
|
||
|
|
||
|
class ACIODeviceEmu {
|
||
|
public:
|
||
|
|
||
|
// attributes
|
||
|
uint8_t node_count = 0;
|
||
|
|
||
|
/*
|
||
|
* Helper functions for getting/setting the message contents
|
||
|
*/
|
||
|
static void set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, uint8_t data_size);
|
||
|
static void set_version(MessageData* data, uint32_t type, uint8_t flag,
|
||
|
uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev,
|
||
|
std::string code);
|
||
|
|
||
|
/*
|
||
|
* This function creates a basic message with optional parameter data.
|
||
|
* If data is set to null, the parameter data will be initialized with 0x00
|
||
|
*/
|
||
|
static MessageData* create_msg(uint8_t addr, uint16_t cmd, uint8_t pid,
|
||
|
size_t data_size, uint8_t *data = nullptr);
|
||
|
static MessageData* create_msg(MessageData* msg_in, size_t data_size, uint8_t *data = nullptr);
|
||
|
|
||
|
/*
|
||
|
* Helper functions for generating messages
|
||
|
*/
|
||
|
static MessageData* create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status);
|
||
|
static MessageData* create_msg_status(MessageData* msg_in, uint8_t status);
|
||
|
|
||
|
virtual ~ACIODeviceEmu() = default;
|
||
|
|
||
|
virtual bool is_applicable(uint8_t node_offset, uint8_t node);
|
||
|
virtual bool parse_msg(MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) = 0;
|
||
|
static void write_msg(const uint8_t *data, size_t size, circular_buffer<uint8_t> *response_buffer);
|
||
|
static void write_msg(MessageData *msg, circular_buffer<uint8_t> *response_buffer);
|
||
|
};
|
||
|
}
|