optimize the structure for op_polll #12

master
Hideaki Tai 3 years ago
parent 6c2b309ef1
commit 4e092ca134

@ -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…
Cancel
Save