From 4bd1446cea1fe4a86012ed9f8d16f13f9f1b3321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Sat, 12 Nov 2022 19:07:52 +0100 Subject: 11. 11. 2022 --- sw/dmx2artnet/monitor | Bin 0 -> 22288 bytes sw/dmx2artnet/monitor.c | 121 +++++++++++++++++++ sw/dmx2artnet/platformio.ini | 8 +- sw/dmx2artnet/src/main.cpp | 174 +++++++++++++-------------- sw/dmx2artnet/src/main.old.cpp | 258 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 463 insertions(+), 98 deletions(-) create mode 100755 sw/dmx2artnet/monitor create mode 100644 sw/dmx2artnet/monitor.c create mode 100644 sw/dmx2artnet/src/main.old.cpp (limited to 'sw/dmx2artnet') diff --git a/sw/dmx2artnet/monitor b/sw/dmx2artnet/monitor new file mode 100755 index 0000000..e7b66e0 Binary files /dev/null and b/sw/dmx2artnet/monitor differ diff --git a/sw/dmx2artnet/monitor.c b/sw/dmx2artnet/monitor.c new file mode 100644 index 0000000..b00e366 --- /dev/null +++ b/sw/dmx2artnet/monitor.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define termios asmtermios +#define winsize asmwinsize +#define termio asmtermio +#include +#undef termios +#undef winsize +#undef termio +#define S0(x) (x ? x : "") +// start bit: low, 2 stop bits high +int rate (int what_rate, int uart) { + int r = 0; + struct termios2 uartattr2; + if (ioctl(uart, TCGETS2, &uartattr2) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "ioctl TCGETS2, fd: %d", uart); + r = 1; + goto r; + } + uartattr2.c_cflag &= ~CBAUD; + uartattr2.c_cflag |= BOTHER; + uartattr2.c_ispeed = what_rate; + uartattr2.c_ospeed = what_rate; + if (ioctl(uart, TCSETS2, &uartattr2) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "ioctl TCSETS2"); + r = 2; + goto r; + } +r: + return r; +} +int main (int argc, char ** argv) { + int r = 0; + if (argc != 1+1) + error_at_line(1, 0, __FILE__, __LINE__, "usage: %s /dev/ttyUSB0", S0(argv[0])); + int uart = open(argv[1], O_RDONLY | O_NOCTTY | O_NDELAY | O_CLOEXEC); + if (uart == -1) + error_at_line(3, errno, __FILE__, __LINE__, "open"); + struct termios uartattr; + if (tcgetattr(uart, &uartattr) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "tcgetattr"); + r = 4; + goto r; + } + uartattr.c_iflag = 0; + uartattr.c_oflag = 0; + uartattr.c_cflag = CS8 | CSTOPB; + uartattr.c_lflag = 0; + if (tcflush(uart, TCIOFLUSH) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "tcflush"); + r = 5; + goto r; + } + if (tcsetattr(uart, TCSANOW, &uartattr) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "tcsetattr"); + r = 6; + goto r; + } + if (tcflush(uart, TCIOFLUSH) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "tcflush"); + r = 15; + goto r; + } + switch (rate(250000, uart)) { + case 1: + r = 20; + goto r; + break; + case 2: + r = 21; + goto r; + break; + default: + break; + } + while (1) { + struct pollfd pollfd; + pollfd.fd = uart; + pollfd.events = POLLIN | POLLERR | POLLHUP | POLLNVAL; + int poll_return; + if ((poll_return = poll(&pollfd, 1, -1)) == -1) { + error_at_line(0, errno, __FILE__, __LINE__, "poll"); + r = 16; + goto r; + } + if (!poll_return) { + error_at_line(0, 0, __FILE__, __LINE__, "poll returned 0"); + r = 17; + goto r; + } + if ((pollfd.revents & POLLERR) | (pollfd.revents & POLLHUP) | (pollfd.revents & POLLNVAL)) { + error_at_line(0, 0, __FILE__, __LINE__, "ERR | HUP | NVAL"); + r = 18; + goto r; + } + char buf[2048]; + ssize_t r = read(uart, buf, 2048); + if (r == -1) + if (errno != EAGAIN) { + error_at_line(0, errno, __FILE__, __LINE__, "read"); + r = 19; + goto r; + } + fwrite(buf, 1, 2048, stdout); + } +r: + if (close(uart) == -1) + error_at_line(22, errno, __FILE__, __LINE__, "close(uart)"); + return r; +} diff --git a/sw/dmx2artnet/platformio.ini b/sw/dmx2artnet/platformio.ini index bf1e75a..cb21119 100644 --- a/sw/dmx2artnet/platformio.ini +++ b/sw/dmx2artnet/platformio.ini @@ -4,10 +4,10 @@ board_build.f_cpu = 160000000L platform = espressif8266 board = nodemcuv2 -monitor_speed = 460800 -upload_speed = 460800 -; build_flags = !echo "-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_PORT=Serial1 -DIP_FORWARD=1 -DMONITOR_SPEED=460800 -DWIFI_PW=$GROMKA_WIFI_PW" -build_flags = !echo "-DIP_FORWARD=1 -DMONITOR_SPEED=460800 -DWIFI_PW=$GROMKA_WIFI_PW" +monitor_speed = 115200 +upload_speed = 1500000 +; build_flags = !echo "-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_PORT=Serial1 -DIP_FORWARD=1 -DMONITOR_SPEED=115200 -DWIFI_PW=$GROMKA_WIFI_PW" +build_flags = !echo "-DIP_FORWARD=1 -DMONITOR_SPEED=115200 -DWIFI_PW=$GROMKA_WIFI_PW" framework = arduino board_build.filesystem = littlefs board_build.ldscript = eagle.flash.4m2m.ld diff --git a/sw/dmx2artnet/src/main.cpp b/sw/dmx2artnet/src/main.cpp index 21ddd18..da5df4e 100644 --- a/sw/dmx2artnet/src/main.cpp +++ b/sw/dmx2artnet/src/main.cpp @@ -1,11 +1,12 @@ -#define DO_SLIP 1 -#define DO_WIFI 1 #include -#include -#ifdef DO_WIFI #include -#include -WiFiUDP u; +#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 @@ -23,7 +24,6 @@ struct artnet { uint8_t length_hi; uint8_t length_lo; unsigned char data[512]; // increase for fun - } __attribute__((packed)); struct udp { uint16_t srcport __attribute__((packed)); @@ -67,47 +67,39 @@ struct artnet_over_slip { 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; +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(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 + 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(); - } else { - if (micros() - last_fall > 87) - mark_after_break++; - } -} */ - +} void setup () { - pinMode(D6, INPUT_PULLUP); + 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 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 +#ifdef SLIP + Serial1.begin(115200); sprintf(p.artnet.name, "Art-Net"); p.artnet.opcode[0] = 0x00; p.artnet.opcode[1] = 0x50; @@ -117,7 +109,7 @@ void setup () { p.artnet.physical = 0; p.artnet.sub_uni = 0; p.artnet.net = 0; - if (digitalRead(D6) == LOW) + if (digitalRead(D3) == LOW) p.udp.srcport = p.udp.dstport = htons(6455); else p.udp.srcport = p.udp.dstport = htons(6454); @@ -132,17 +124,18 @@ void setup () { 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); +#else + Serial1.begin(MONITOR_SPEED); +#endif + attachInterrupt(interrupt, isr, CHANGE); } -unsigned char recording[sizeof p.artnet.data * 2]; -#ifdef DO_SLIP +#ifdef 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 +void loop() { +#ifdef SLIP unsigned avail = SLIP.availableForWrite(); if (slip_off < slip_len && avail) { if (avail > slip_len-slip_off) @@ -150,46 +143,42 @@ void loop () { 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 /* 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++; + } } - 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 + 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(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.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++) @@ -217,14 +206,11 @@ void loop () { } slip_buf[slip_len++] = END; } +#else + // DEBUG("ch1: " + p.artnet.data[0]); #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; + attachInterrupt(interrupt, isr, CHANGE); + last_fall = 0; } } diff --git a/sw/dmx2artnet/src/main.old.cpp b/sw/dmx2artnet/src/main.old.cpp new file mode 100644 index 0000000..88d9c80 --- /dev/null +++ b/sw/dmx2artnet/src/main.old.cpp @@ -0,0 +1,258 @@ +#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(); + } +} -- cgit v1.2.3