diff options
Diffstat (limited to 'sw/dmx2artnet/src/main.cpp')
-rw-r--r-- | sw/dmx2artnet/src/main.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/sw/dmx2artnet/src/main.cpp b/sw/dmx2artnet/src/main.cpp new file mode 100644 index 0000000..2da28ae --- /dev/null +++ b/sw/dmx2artnet/src/main.cpp @@ -0,0 +1,179 @@ +#include <Arduino.h> +#include <WiFiUdp.h> +#include <ESP8266WiFi.h> +#include <ESP8266WiFiMulti.h> +#define END 0xc0 +#define ESC 0xdb +#define ESC_END 0xdc +#define ESC_ESC 0xdd +WiFiUDP u; +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 w = 0; +unsigned long č = 0; +unsigned char t; +void setup () { + pinMode(D0, OUTPUT); + Serial.begin(250000, SERIAL_8N2); + Serial.swap(); + Serial1.begin(/* MONITOR_SPEED */ 115200); + // WiFi.softAP("dmx2artnet", NULL, 11, 0, 8); + WiFi.begin("OpenWrt", NULL); + // WiFi.begin("Hell Patrol", WIFI_PW); + u.begin(6454); + 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; + 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); +} +char slip_buf[sizeof p * 2 + 1]; +unsigned char recording[sizeof p.artnet.data * 2]; +unsigned slip_off = 0; +unsigned slip_len = 0; +#define SLIP Serial1 +void loop () { + 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); + } + if (Serial.available()) { + č = millis(); + if (w < sizeof p.artnet.data * 2) + recording[w++] = Serial.read(); + else + Serial.read(); + } + if (č + 1 < millis() && w) { + unsigned T; + for (T = 0; T < w; T++) // prvi kanal ne sme biti 0, tako zaznamo začetek paketa + if (recording[T] > 1) + break; + memcpy(p.artnet.data, recording + T, sizeof p.artnet.data); + unsigned l = w-T; + if (l > sizeof p.artnet.data) + l = sizeof p.artnet.data; + /* l++; + while (--l) + if (p.data[l-1]) + break; */ + if (!t) { + p.artnet.length_hi = l / 256; + p.artnet.length_lo = l % 256; + 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(); + 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/2+sizeof p%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; + } + } + /* + 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])); + */ + w = 0; + } +} |