summaryrefslogblamecommitdiffstats
path: root/sw/dmx2artnet/src/main.cpp
blob: 21ddd187efc2824ead51c646e8d7deb715a1d209 (plain) (tree)
1
2
3
4
5
6
7
8
9

                 

                    
              

                             

          



                    























































                                                                                                   
                     
























                                                    
               
                                  

                                         
              
                                                  



                            
                                                     

                                           
                      
      








                                          



                                                            










                                                         
                                                                   
 
                                                  

                                

                      
      

                    
              





                                                                 
      
                                 
                              




                                                       






                                                                                                    
                                             




                                                                                           





                                                 
                                    

                                                     
              



                                                                                                         

              





                                                                                                                
                                                                                          























                                                                                       
      









                                                                                                      
#define DO_SLIP 1
#define DO_WIFI 1
#include <Arduino.h>
#include <WiFiUdp.h>
#ifdef DO_WIFI
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
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 send = 0;
IRAM_ATTR void isr () {
	if (digitalRead(D6) == LOW) {
		if (mark_after_break) {
			// mark_after_break = 0;
			// send = w-1;
			// w = 0;
			mark_after_break = w = 0;

#ifndef DO_SLIP
			digitalWrite(D4, led++ % 2);
#endif
		}
		last_fall = micros();
	} else {
		if (micros() - last_fall > 87)
			mark_after_break++;
	}
} */

void setup () {
	pinMode(D6, INPUT_PULLUP);
	Serial.begin(250000, SERIAL_8N2);
	Serial.swap();
#ifdef DO_SLIP
	Serial1.begin(/* MONITOR_SPEED */ 115200);
#else
	pinMode(D4, OUTPUT);
#endif
#ifdef DO_WIFI
	// WiFi.softAP("dmx2artnet", NULL, 11, 0, 8);
	// WiFi.begin("OpenWrt", NULL);
	WiFi.begin("Hell Patrol", WIFI_PW);
	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);
	// attachInterrupt(digitalPinToInterrupt(D6), isr, CHANGE);
}
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 () {
#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.available()) {
		č = micros();
		if (w < sizeof p.artnet.data * 2)
			recording[w++] = Serial.read();
		else
			Serial.read();
	}
	if (č + 200 < micros() && w) {
	// if (send) {
		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 (T = 0; T < w; T++) // prvi kanal ne sme biti 0, tako zaznamo začetek paketa
			if (recording[T] > 1)
				break; */
		/* 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;
		/* l++;
		while (--l)
			if (p.data[l-1])
				break; */
		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]));
		*/
		w = 0;
	}
}