optimize the structure for op_polll #12
This commit is contained in:
parent
6c2b309ef1
commit
4e092ca134
234
Artnet.h
234
Artnet.h
@ -131,7 +131,7 @@ namespace arx {
|
||||
#else
|
||||
template <uint16_t SIZE>
|
||||
using Array = arx::vector<uint8_t, SIZE>;
|
||||
using CallbackMap = arx::map<uint32_t, CallbackType, 8>;
|
||||
using CallbackMap = arx::map<uint32_t, CallbackType, 4>;
|
||||
using namespace arx;
|
||||
#endif
|
||||
|
||||
@ -197,15 +197,6 @@ namespace arx {
|
||||
#endif
|
||||
virtual ~Sender_() {}
|
||||
|
||||
void net(const uint8_t n) { target_net = n & 0x7F; }
|
||||
void subnet(const uint8_t s) { target_subnet = s & 0x0F; }
|
||||
void universe(const uint8_t u) { target_universe = u & 0x0F; }
|
||||
void universe15bit(const uint8_t u) {
|
||||
net((u >> 8) & 0xFF);
|
||||
subnet((u >> 4) & 0x0F);
|
||||
universe((u >> 0) & 0x0F);
|
||||
}
|
||||
|
||||
void set(const uint8_t* const data, const uint16_t size = 512) {
|
||||
packet[IDX(Index::PHYSICAL)] = phy;
|
||||
packet[IDX(Index::NET)] = target_net;
|
||||
@ -216,14 +207,16 @@ namespace arx {
|
||||
}
|
||||
|
||||
void set(const uint32_t universe_, const uint8_t* const data, const uint16_t size = 512) {
|
||||
universe15bit(universe_);
|
||||
target_net = (universe_ >> 8) & 0x7F;
|
||||
target_subnet = (universe_ >> 4) & 0x0F;
|
||||
target_universe = universe_ & 0x0F;
|
||||
set(data, size);
|
||||
}
|
||||
|
||||
void set(const uint8_t net_, const uint8_t subnet_, const uint8_t universe_, const uint8_t* const data, const uint16_t size = 512) {
|
||||
net(net_);
|
||||
subnet(subnet_);
|
||||
universe(universe_);
|
||||
target_net = net_ & 0x7F;
|
||||
target_subnet = subnet_ & 0x0F;
|
||||
target_universe = universe_ & 0x0F;
|
||||
set(data, size);
|
||||
}
|
||||
|
||||
@ -259,67 +252,6 @@ namespace arx {
|
||||
|
||||
void physical(const uint8_t i) const { phy = constrain(i, 0, 3); }
|
||||
|
||||
// void poll_reply(const IPAddress& remote_ip, const uint16_t remote_port) {
|
||||
void poll_reply() {
|
||||
ArtPollReply r;
|
||||
for (size_t i = 0; i < ID_LENGTH; i++) r.id[i] = static_cast<uint8_t>(ID[i]);
|
||||
r.op_code_l = ((uint16_t)OpCode::PollReply >> 0) & 0x00FF;
|
||||
r.op_code_h = ((uint16_t)OpCode::PollReply >> 8) & 0x00FF;
|
||||
#ifdef ARTNET_ENABLE_WIFI
|
||||
IPAddress my_ip = WiFi.localIP();
|
||||
IPAddress my_subnet = WiFi.subnetMask();
|
||||
#endif
|
||||
#ifdef ARTNET_ENABLE_ETHER
|
||||
IPAddress my_ip = Ethernet.localIP();
|
||||
IPAddress my_subnet = Ethernet.subnetMask();
|
||||
#endif
|
||||
for (size_t i = 0; i < 4; ++i) r.ip[i] = my_ip[i];
|
||||
r.port_l = (DEFAULT_PORT >> 0) & 0xFF;
|
||||
r.port_h = (DEFAULT_PORT >> 8) & 0xFF;
|
||||
r.ver_h = (PROTOCOL_VER >> 8) & 0x00FF;
|
||||
r.ver_l = (PROTOCOL_VER >> 0) & 0x00FF;
|
||||
r.net_sw = 0; // TODO:
|
||||
r.sub_sw = 0; // TODO:
|
||||
r.oem_h = 0; // https://github.com/tobiasebsen/ArtNode/blob/master/src/Art-NetOemCodes.h
|
||||
r.oem_l = 0xFF; // OemUnknown
|
||||
r.ubea_ver = 0; // UBEA not programmed
|
||||
r.status_1 = 0x00; // Unknown / Normal
|
||||
r.esta_man_l = 0; // No EATA manufacture code
|
||||
r.esta_man_h = 0; // No ESTA manufacture code
|
||||
char short_name[18] = "Arduino ArtNet";
|
||||
memcpy(r.short_name, short_name, sizeof(short_name));
|
||||
char long_name[64] = "Arduino ArtNet Protocol by hideakitai/ArtNet";
|
||||
memcpy(r.long_name, long_name, sizeof(long_name));
|
||||
static size_t counts = 0;
|
||||
char node_report[64];
|
||||
sprintf(node_report, "#0001 [%d] Arduino ArtNet enabled", counts++);
|
||||
memcpy(r.node_report, node_report, sizeof(node_report));
|
||||
r.num_ports_h = 0; // Reserved
|
||||
r.num_ports_l = 1; // This library implements only 1 port
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
r.port_types[i] = 0xC0; // I/O available by DMX512
|
||||
r.good_input[i] = 0x80; // Data received without error
|
||||
r.good_output[i] = 0x80; // Data transmittedj without error
|
||||
r.sw_in[i] = 0; // TODO:
|
||||
r.sw_out[i] = 0; // TODO:
|
||||
}
|
||||
r.sw_video = 0; // Video display shows local data
|
||||
r.sw_macro = 0; // No support for macro key inputs
|
||||
r.sw_remote = 0; // No support for remote trigger inputs
|
||||
memset(r.spare, 0x00, 3);
|
||||
r.style = 0x00; // A DMX to / from Art-Net device
|
||||
memset(r.mac, 0x00, 6); // Do not supply mac address
|
||||
for (size_t i = 0; i < 4; ++i) r.bind_ip[i] = my_ip[i];
|
||||
r.bind_index = 0;
|
||||
r.status_2 = 0x08; // sACN capable (maybe)
|
||||
memset(r.filler, 0x00, 26);
|
||||
|
||||
static const IPAddress local_broadcast_addr = IPAddress((uint32_t)my_ip | ~(uint32_t)my_subnet);
|
||||
stream->beginPacket(local_broadcast_addr, DEFAULT_PORT);
|
||||
stream->write(r.b, sizeof(ArtPollReply));
|
||||
stream->endPacket();
|
||||
}
|
||||
|
||||
uint8_t sequence() const { return seq; }
|
||||
|
||||
protected:
|
||||
@ -340,6 +272,11 @@ namespace arx {
|
||||
Array<PACKET_SIZE> packet;
|
||||
IPAddress remote_ip;
|
||||
uint16_t remote_port;
|
||||
uint8_t univ_net;
|
||||
uint8_t univ_subnet;
|
||||
String short_name{"Arduino ArtNet"};
|
||||
String long_name{"Ardino ArtNet Protocol by hideakitai/ArtNet"};
|
||||
String node_report{""};
|
||||
CallbackMap callbacks;
|
||||
CallbackAllType callback_all;
|
||||
S* stream;
|
||||
@ -373,6 +310,7 @@ namespace arx {
|
||||
case OPC(OpCode::Poll): {
|
||||
remote_ip = stream->S::remoteIP();
|
||||
remote_port = (uint16_t)stream->S::remotePort();
|
||||
poll_reply();
|
||||
return OpCode::Poll;
|
||||
}
|
||||
default: {
|
||||
@ -411,10 +349,10 @@ namespace arx {
|
||||
inline uint8_t physical() const {
|
||||
return packet[IDX(Index::PHYSICAL)];
|
||||
}
|
||||
inline uint8_t net() const {
|
||||
uint8_t net() const {
|
||||
return packet[IDX(Index::NET)] & 0x7F;
|
||||
}
|
||||
inline uint8_t subnet() const {
|
||||
uint8_t subnet() const {
|
||||
return (packet[IDX(Index::SUBUNI)] >> 4) & 0x0F;
|
||||
}
|
||||
inline uint8_t universe() const {
|
||||
@ -436,15 +374,42 @@ namespace arx {
|
||||
return packet[HEADER_SIZE + i];
|
||||
}
|
||||
|
||||
void subscribe_net(const uint8_t n) {
|
||||
univ_net = n;
|
||||
}
|
||||
|
||||
void subscribe_subnet(const uint8_t sn) {
|
||||
univ_subnet = sn;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline auto subscribe(const uint32_t universe, F&& func)
|
||||
inline auto subscribe(const uint8_t universe, F&& func)
|
||||
-> std::enable_if_t<arx::is_callable<F>::value> {
|
||||
callbacks.insert(make_pair(universe, arx::function_traits<F>::cast(func)));
|
||||
if (callbacks.size() >= 4) {
|
||||
Serial.println(F("too many callbacks"));
|
||||
} else {
|
||||
if (universe > 0xF) {
|
||||
Serial.println(F("universe out of bounds"));
|
||||
return;
|
||||
} else {
|
||||
uint32_t u = ((uint32_t)univ_net << 8) | ((uint32_t)univ_subnet << 4) | (uint32_t)universe;
|
||||
callbacks.insert(make_pair(u, arx::function_traits<F>::cast(func)));
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename F>
|
||||
inline auto subscribe(const uint32_t universe, F* func)
|
||||
inline auto subscribe(const uint8_t universe, F* func)
|
||||
-> std::enable_if_t<arx::is_callable<F>::value> {
|
||||
callbacks.insert(make_pair(universe, arx::function_traits<F>::cast(func)));
|
||||
if (callbacks.size() >= 4) {
|
||||
Serial.println(F("too many callbacks"));
|
||||
} else {
|
||||
if (universe > 0xF) {
|
||||
Serial.println(F("universe out of bounds"));
|
||||
} else {
|
||||
uint32_t u = ((uint32_t)univ_net << 8) | ((uint32_t)univ_subnet << 4) | (uint32_t)universe;
|
||||
callbacks.insert(make_pair(u, arx::function_traits<F>::cast(func)));
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename F>
|
||||
inline auto subscribe(F&& func)
|
||||
@ -456,20 +421,8 @@ namespace arx {
|
||||
-> std::enable_if_t<arx::is_callable<F>::value> {
|
||||
callback_all = arx::function_traits<F>::cast(func);
|
||||
}
|
||||
template <typename F>
|
||||
inline auto subscribe(const uint8_t net, const uint8_t subnet, const uint8_t universe, F&& func)
|
||||
-> std::enable_if_t<arx::is_callable<F>::value> {
|
||||
uint32_t u = ((uint32_t)net << 8) | ((uint32_t)subnet << 4) | (uint32_t)universe;
|
||||
subscribe(u, func);
|
||||
}
|
||||
template <typename F>
|
||||
inline auto subscribe(const uint8_t net, const uint8_t subnet, const uint8_t universe, F* func)
|
||||
-> std::enable_if_t<arx::is_callable<F>::value> {
|
||||
uint32_t u = ((uint32_t)net << 8) | ((uint32_t)subnet << 4) | (uint32_t)universe;
|
||||
subscribe(u, func);
|
||||
}
|
||||
|
||||
inline void unsubscribe(const uint32_t universe) {
|
||||
inline void unsubscribe(const uint8_t universe) {
|
||||
auto it = callbacks.find(universe);
|
||||
if (it != callbacks.end())
|
||||
callbacks.erase(it);
|
||||
@ -477,10 +430,6 @@ namespace arx {
|
||||
inline void unsubscribe() {
|
||||
callback_all = nullptr;
|
||||
}
|
||||
inline void unsubscribe(const uint8_t net, const uint8_t subnet, const uint8_t universe) {
|
||||
uint32_t u = ((uint32_t)net << 8) | ((uint32_t)subnet << 4) | (uint32_t)universe;
|
||||
unsubscribe(u);
|
||||
}
|
||||
|
||||
inline void clear_subscribers() {
|
||||
unsubscribe();
|
||||
@ -504,6 +453,17 @@ namespace arx {
|
||||
forward(u, leds, num);
|
||||
}
|
||||
#endif
|
||||
void shortname(const String& sn) {
|
||||
short_name = sn;
|
||||
}
|
||||
|
||||
void longname(const String& ln) {
|
||||
long_name = ln;
|
||||
}
|
||||
|
||||
void nodereport(const String& nr) {
|
||||
node_report = nr;
|
||||
}
|
||||
|
||||
protected:
|
||||
void attach(S& s) {
|
||||
@ -519,6 +479,73 @@ namespace arx {
|
||||
const char* idptr = reinterpret_cast<const char*>(p);
|
||||
return !strcmp(ID, idptr);
|
||||
}
|
||||
|
||||
void poll_reply() {
|
||||
ArtPollReply r;
|
||||
for (size_t i = 0; i < ID_LENGTH; i++) r.id[i] = static_cast<uint8_t>(ID[i]);
|
||||
r.op_code_l = ((uint16_t)OpCode::PollReply >> 0) & 0x00FF;
|
||||
r.op_code_h = ((uint16_t)OpCode::PollReply >> 8) & 0x00FF;
|
||||
#ifdef ARTNET_ENABLE_WIFI
|
||||
IPAddress my_ip = WiFi.localIP();
|
||||
IPAddress my_subnet = WiFi.subnetMask();
|
||||
WiFi.macAddress(r.mac);
|
||||
#endif
|
||||
#ifdef ARTNET_ENABLE_ETHER
|
||||
IPAddress my_ip = Ethernet.localIP();
|
||||
IPAddress my_subnet = Ethernet.subnetMask();
|
||||
Ethernet.MACAddress(r.mac);
|
||||
#endif
|
||||
for (size_t i = 0; i < 4; ++i) r.ip[i] = my_ip[i];
|
||||
r.port_l = (DEFAULT_PORT >> 0) & 0xFF;
|
||||
r.port_h = (DEFAULT_PORT >> 8) & 0xFF;
|
||||
r.ver_h = (PROTOCOL_VER >> 8) & 0x00FF;
|
||||
r.ver_l = (PROTOCOL_VER >> 0) & 0x00FF;
|
||||
r.oem_h = 0; // https://github.com/tobiasebsen/ArtNode/blob/master/src/Art-NetOemCodes.h
|
||||
r.oem_l = 0xFF; // OemUnknown
|
||||
r.ubea_ver = 0; // UBEA not programmed
|
||||
r.status_1 = 0x00; // Unknown / Normal
|
||||
r.esta_man_l = 0; // No EATA manufacture code
|
||||
r.esta_man_h = 0; // No ESTA manufacture code
|
||||
memset(r.short_name, 0, 18);
|
||||
memset(r.long_name, 0, 64);
|
||||
memset(r.node_report, 0, 64);
|
||||
memcpy(r.short_name, short_name.c_str(), short_name.length());
|
||||
memcpy(r.long_name, long_name.c_str(), long_name.length());
|
||||
memcpy(r.node_report, node_report.c_str(), node_report.length());
|
||||
r.num_ports_h = 0; // Reserved
|
||||
r.num_ports_l = callbacks.size(); // This library implements only 4 port
|
||||
memset(r.sw_in, 0, 4);
|
||||
memset(r.sw_out, 0, 4);
|
||||
memset(r.port_types, 0, 4);
|
||||
memset(r.good_input, 0, 4);
|
||||
memset(r.good_output, 0, 4);
|
||||
size_t i = 0;
|
||||
for (const auto& pair : callbacks) {
|
||||
r.net_sw = (pair.first >> 8) & 0x7F; // all callbacks have same value
|
||||
r.sub_sw = (pair.first >> 4) & 0x0F;
|
||||
r.sw_in[i] = pair.first & 0x0F;
|
||||
r.sw_out[i] = i; // dummy: output port is flexible
|
||||
r.port_types[i] = 0xC0; // I/O available by DMX512
|
||||
r.good_input[i] = 0x80; // Data received without error
|
||||
r.good_output[i] = 0x80; // Data transmitted without error
|
||||
if (++i >= 4) break;
|
||||
}
|
||||
r.sw_video = 0; // Video display shows local data
|
||||
r.sw_macro = 0; // No support for macro key inputs
|
||||
r.sw_remote = 0; // No support for remote trigger inputs
|
||||
memset(r.spare, 0x00, 3);
|
||||
r.style = 0x00; // A DMX to / from Art-Net device
|
||||
for (size_t i = 0; i < 4; ++i) r.bind_ip[i] = my_ip[i];
|
||||
r.bind_index = 0;
|
||||
r.status_2 = 0x08; // sACN capable
|
||||
memset(r.filler, 0x00, 26);
|
||||
|
||||
static const IPAddress local_broadcast_addr = IPAddress((uint32_t)my_ip | ~(uint32_t)my_subnet);
|
||||
stream->beginPacket(local_broadcast_addr, DEFAULT_PORT);
|
||||
stream->write(r.b, sizeof(ArtPollReply));
|
||||
stream->endPacket();
|
||||
}
|
||||
|
||||
}; // namespace artnet
|
||||
|
||||
template <typename S>
|
||||
@ -533,16 +560,7 @@ namespace arx {
|
||||
}
|
||||
|
||||
void parse() {
|
||||
OpCode op_code = this->Receiver_<S>::parse();
|
||||
switch (op_code) {
|
||||
case OpCode::Poll: {
|
||||
this->Sender_<S>::poll_reply();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->Receiver_<S>::parse();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user