#include #include #ifdef DO_WIFI #include #include WiFiUDP u; #endif #define END 0xc0 #define ESC 0xdb #define ESC_END 0xdc #define ESC_ESC 0xdd struct artnet { char name[8]; // Art-Net\0 char opcode[2]; // 0x5000 in LE: { 0x00, 0x50 } uint8_t version_hi; // 0 uint8_t version_lo; // 14 uint8_t sequence; // set to 0 to disable sequencing uint8_t physical; // original universe uint8_t sub_uni; uint8_t net; uint8_t length_hi; uint8_t length_lo; unsigned char data[512]; // increase for fun } __attribute__((packed)); struct udp { uint16_t srcport __attribute__((packed)); uint16_t dstport __attribute__((packed)); uint16_t length __attribute__((packed)); uint16_t checksum __attribute__((packed)); } __attribute__((packed)); #define LOW_DELAY (1 << 4) #define HIGH_THROUGHPUT (1 << 3) #define HIGH_RELIABILITY (1 << 2) #define ROUTINE (0 << 5) #define PRIORITY (1 << 5) #define IMMEDIATE (1 << 6) #define FLASH (PRIORITY | IMMEDIATE) #define FLASH_OVERRIDE (1 << 7) #define CRITICAL (FLASH_OVERRIDE | PRIORITY) #define INETCTRL (FLASH_OVERRIDE | IMMEDIATE) #define NETCTRL (FLASH_OVERRIDE | FLASH) #define HEADLENOR (1 << 6) /* always bitwiseOR the headlen with this to apply the version number */ #define EVIL (1 << 15) #define DF (1 << 14) #define MF (1 << 13) #define ICMP 1 #define TCP 6 #define UDP 17 struct ip { uint8_t headlen; uint8_t srvtype; uint16_t length __attribute__((packed)); uint16_t identifier __attribute__((packed)); uint16_t foffset __attribute__((packed)); uint8_t ttl; uint8_t protocol; uint16_t checksum; unsigned char src[4]; unsigned char dst[4]; } __attribute__((packed)); struct artnet_over_slip { struct ip ip; struct udp udp; struct artnet artnet; } __attribute__((packed)); struct artnet_over_slip p; unsigned long č = 0; volatile unsigned w = 0; volatile unsigned long last_fall = 0; volatile unsigned long mark_after_break = 0; volatile unsigned char led = 0; volatile unsigned char after_break_detected = 0; // volatile unsigned send = 0; void after_break (); void wait_for_break (); #define INT_RX D7 IRAM_ATTR void isr () { if (digitalRead(INT_RX) == LOW) { if (mark_after_break) { mark_after_break = w = 0; #ifndef DO_SLIP // digitalWrite(D4, led++ % 2); // Serial1.println("low"); #endif after_break_detected++; } last_fall = micros(); } else { if (micros() - last_fall > 87) mark_after_break++; } } unsigned serial_status = 0; void after_break() { detachInterrupt(digitalPinToInterrupt(INT_RX)); if (!serial_status++) Serial.begin(250000, SERIAL_8N2); #ifndef DO_SLIP Serial1.println("after_break"); #endif } void wait_for_break () { if (serial_status) Serial.end(); serial_status = 0; attachInterrupt(digitalPinToInterrupt(INT_RX), isr, CHANGE); } void setup () { pinMode(D6, INPUT_PULLUP); pinMode(INT_RX, INPUT); Serial.swap(); #ifdef DO_SLIP Serial1.begin(115200); #else pinMode(D4, SPECIAL); Serial1.begin(MONITOR_SPEED); #endif #ifdef DO_WIFI // WiFi.softAP("dmx2artnet", NULL, 11, 0, 8); // WiFi.begin("OpenWrt", NULL); // WiFi.begin("Hell Patrol", WIFI_PW); WiFi.begin("a", NULL); u.begin(6454); #endif sprintf(p.artnet.name, "Art-Net"); p.artnet.opcode[0] = 0x00; p.artnet.opcode[1] = 0x50; p.artnet.version_hi = 0; p.artnet.version_lo = 14; p.artnet.sequence = 0; p.artnet.physical = 0; p.artnet.sub_uni = 0; p.artnet.net = 0; if (digitalRead(D6) == LOW) p.udp.srcport = p.udp.dstport = htons(6455); else p.udp.srcport = p.udp.dstport = htons(6454); p.udp.checksum = 0; p.ip.headlen = HEADLENOR | 5; p.ip.srvtype = 0; p.ip.foffset = 0; p.ip.ttl = 255; p.ip.protocol = UDP; p.ip.src[0] = 2; p.ip.src[1] = (ESP.getChipId() & 0xff0000) >> 16; p.ip.src[2] = (ESP.getChipId() & 0xff00) >> 8; p.ip.src[3] = (ESP.getChipId() & 0xff); memset(p.ip.dst, 255, 4); wait_for_break(); #ifndef DO_SLIP Serial1.println("setupfin"); #endif } unsigned char recording[sizeof p.artnet.data * 2]; #ifdef DO_SLIP char slip_buf[sizeof p * 2 + 1]; unsigned slip_off = 0; unsigned slip_len = 0; #endif #define SLIP Serial1 void loop () { if (after_break_detected) { after_break(); after_break_detected = 0; } #ifdef DO_SLIP unsigned avail = SLIP.availableForWrite(); if (slip_off < slip_len && avail) { if (avail > slip_len-slip_off) avail = slip_len-slip_off; slip_off += SLIP.write(slip_buf+slip_off, avail); } #endif if (serial_status && Serial.available()) { #ifndef DO_SLIP Serial1.println("Sa"); #endif č = micros(); if (w < sizeof p.artnet.data * 2) recording[w++] = Serial.read(); else Serial.read(); } if (w >= sizeof p.artnet.data || (w && č + 200 < micros())) { unsigned t = 0; /* if (w == sizeof p.artnet.data) // če smo break zaznali kot bajt, ga odstranimo t = 1; */ unsigned l = w-t-1; // en je tip /* for (unsigned i = 0; i < sizeof p.artnet.data; i++) // takes too long??? if (!(hack_for_midi_flash && recording[t + 1] == 255)) p.artnet.data[i] = recording[t + 1]; */ memcpy(p.artnet.data, recording + t + 1, sizeof p.artnet.data); if (l > sizeof p.artnet.data) l = sizeof p.artnet.data; if (!recording[t]) { p.artnet.length_hi = l / 256; p.artnet.length_lo = l % 256; #ifdef DO_WIFI IPAddress b(255, 255, 255, 255); u.beginPacket(b, 6454); u.write((unsigned char *) &p.artnet, sizeof p.artnet - sizeof p.artnet.data + l); u.endPacket(); #endif #ifdef DO_SLIP if (slip_off >= slip_len) { p.ip.identifier = htons(millis()); p.udp.length = htons(sizeof p.udp + sizeof p.artnet - sizeof p.artnet.data + l); p.ip.length = htons(sizeof p - sizeof p.artnet.data + l); p.ip.checksum = 0; uint32_t sum = 0; for (unsigned i = 0; i < sizeof p.ip/2+sizeof p.ip%2; i++) sum += ntohs(((uint16_t *) &p)[i]); while (sum >> 16) sum = (sum >> 16) + sum % 65536; p.ip.checksum = htons(~sum); slip_len = 0; slip_off = 0; for (unsigned i = 0; i < sizeof p; i++) { unsigned char val = ((unsigned char *) &p)[i]; switch (val) { case ESC: slip_buf[slip_len++] = ESC; slip_buf[slip_len++] = ESC_ESC; break; case END: slip_buf[slip_len++] = ESC; slip_buf[slip_len++] = ESC_END; break; default: slip_buf[slip_len++] = val; break; } } slip_buf[slip_len++] = END; } #endif } /* Serial1.println("dolžina podatkov " + String(w-T) + ", tip: " + String(t)); for (unsigned i = 0; i < l; i++) if (p.artnet.data[i]) Serial1.println("\t" + String(i+1) + ": " + String(p.artnet.data[i])); */ #ifndef DO_SLIP Serial1.println("loop: wfb, w=" + String(w)); #endif w = 0; wait_for_break(); } }