blob: da5df4ec7e34141d35730a9656e2b5596202d97a (
plain) (
tree)
|
|
#include <Arduino.h>
#include <ESP8266WiFi.h>
#define INT_RX D6
#define SLIP Serial1
// #undef SLIP
#ifdef SLIP
#define DEBUG(x)
#else
#define DEBUG(x) Serial1.println(x)
#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 n = 0;
volatile int interrupt = digitalPinToInterrupt(INT_RX);
volatile unsigned long last_fall = 0;
volatile unsigned led = 0;
volatile unsigned recording = 0;
unsigned long last_byte = 0;
unsigned long flash_hack = 0;
unsigned sent_packets = 0;
IRAM_ATTR void isr () {
if (digitalRead(INT_RX) == HIGH) {
if (last_fall && micros() - last_fall > 87) {
recording++;
while (Serial.available())
Serial.read();
last_byte = micros();
n = 0;
detachInterrupt(interrupt);
}
} else
last_fall = micros();
}
void setup () {
WiFi.mode(WIFI_OFF);
pinMode(D4, SPECIAL);
pinMode(INT_RX, INPUT);
pinMode(D5, INPUT_PULLUP);
pinMode(D3, INPUT_PULLUP);
if (digitalRead(D5) == LOW)
flash_hack++;
Serial.begin(250000, SERIAL_8N2);
Serial.swap();
#ifdef SLIP
Serial1.begin(115200);
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(D3) == 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);
#else
Serial1.begin(MONITOR_SPEED);
#endif
attachInterrupt(interrupt, isr, CHANGE);
}
#ifdef SLIP
char slip_buf[sizeof p * 2 + 1];
unsigned slip_off = 0;
unsigned slip_len = 0;
#endif
void loop() {
#ifdef 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 /* while */ (n <= sizeof p.artnet.data && ((!n && micros() - last_byte < 1e6) || micros() - last_byte < 50)) {
if (recording && Serial.available()) {
unsigned char r = Serial.read();
last_byte = micros();
if (!n) {
/*
if (r) {
n = 0;
return;
}
n++;
continue;
*/
recording = !r;
attachInterrupt(interrupt, isr, CHANGE);
last_fall = 0;
n++;
return;
}
if (!flash_hack || r != 255)
p.artnet.data[n-1] = r;
n++;
}
}
else if (recording) {
recording = 0;
if (n != 513)
DEBUG("n: " + String(n));
if (n == sizeof p.artnet.data + 1) {
p.artnet.length_hi = (n-1) / 256;
p.artnet.length_lo = (n-1) % 256;
#ifdef SLIP
if (slip_off >= slip_len) {
p.ip.identifier = htons(sent_packets++);
p.udp.length = htons(sizeof p.udp + sizeof p.artnet);
p.ip.length = htons(sizeof p);
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;
}
#else
// DEBUG("ch1: " + p.artnet.data[0]);
#endif
}
attachInterrupt(interrupt, isr, CHANGE);
last_fall = 0;
}
}
|