-
Notifications
You must be signed in to change notification settings - Fork 0
/
serial_protocol.hpp
146 lines (114 loc) · 3.15 KB
/
serial_protocol.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once
#include <stdint.h>
#include "maple/maple_bus_commands.hpp"
#include "crc32.h"
namespace serial_load {
consteval uint32_t gen_cmd(const char * s)
{
uint32_t x = 0
| s[0] << 0
| s[1] << 8
| s[2] << 16
| s[3] << 24;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return x;
}
union command_reply {
uint8_t u8[16];
uint32_t u32[4];
struct {
uint32_t cmd;
uint32_t arg[2];
uint32_t crc;
};
};
static inline uint32_t le_bswap(const uint32_t n)
{
if constexpr (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
return n;
else
return __builtin_bswap32(n);
}
constexpr union command_reply command_reply(uint32_t cmd, uint32_t arg0, uint32_t arg1)
{
union command_reply command = {
.cmd = le_bswap(cmd),
.arg = { le_bswap(arg0), le_bswap(arg1) },
.crc = 0,
};
command.crc = le_bswap(crc32(command.u8, 12));
return command;
}
namespace command {
constexpr uint32_t _write = gen_cmd("WRTE");
constexpr uint32_t _read = gen_cmd("READ");
constexpr uint32_t _jump = gen_cmd("JUMP");
constexpr uint32_t _speed = gen_cmd("SPED");
constexpr uint32_t _maple_raw = gen_cmd("MPRW");
static_assert(_write == 0x2cc46ed8);
static_assert(_read == 0xf18d57c7);
static_assert(_jump == 0xa6696f38);
static_assert(_speed == 0x27a7a9f4);
static_assert(_maple_raw == 0xb62422e0);
constexpr union command_reply write(uint32_t dest, uint32_t size)
{
return command_reply(_write, dest, size);
}
constexpr union command_reply read(uint32_t dest, uint32_t size)
{
return command_reply(_read, dest, size);
}
constexpr union command_reply jump(uint32_t dest)
{
return command_reply(_jump, dest, 0);
}
constexpr union command_reply speed(uint32_t speed)
{
return command_reply(_speed, speed, 0);
}
constexpr union command_reply maple_raw(uint32_t send_size, uint32_t recv_size)
{
return command_reply(_maple_raw, send_size, recv_size);
}
}
namespace reply {
constexpr uint32_t _write = gen_cmd("wrte");
constexpr uint32_t _read = gen_cmd("read");
constexpr uint32_t _jump = gen_cmd("jump");
constexpr uint32_t _speed = gen_cmd("sped");
constexpr uint32_t _maple_raw = gen_cmd("mprw");
constexpr uint32_t _crc = gen_cmd("rcrc");
static_assert(_write == 0x8c661aaa);
static_assert(_read == 0x512f23b5);
static_assert(_jump == 0x06cb1b4a);
static_assert(_speed == 0x8705dd86);
static_assert(_maple_raw == 0x16865692);
static_assert(_crc == 0xcc9aab7c);
constexpr union command_reply write(uint32_t dest, uint32_t size)
{
return command_reply(_write, dest, size);
}
constexpr union command_reply read(uint32_t dest, uint32_t size)
{
return command_reply(_read, dest, size);
}
constexpr union command_reply jump(uint32_t dest)
{
return command_reply(_jump, dest, 0);
}
constexpr union command_reply speed(uint32_t speed)
{
return command_reply(_speed, speed, 0);
}
constexpr union command_reply crc(uint32_t crc)
{
return command_reply(_crc, crc, 0);
}
constexpr union command_reply maple_raw(uint32_t send_size, uint32_t recv_size)
{
return command_reply(_maple_raw, send_size, recv_size);
}
}
}