summaryrefslogtreecommitdiffstats
path: root/sw/dmx2artnet/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sw/dmx2artnet/src/main.cpp')
-rw-r--r--sw/dmx2artnet/src/main.cpp179
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;
+ }
+}