DMX interface (DMX in/out, Art-Net in/out, DMX patch) http://mbed.org/users/okini3939/notebook/dmx-platform/

Dependencies:   ChaNFSSD EthernetNetIf mbed ConfigFile ChaNFS DmxArtNet

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Thu Mar 01 01:40:07 2012 +0000
Commit message:

Changed in this revision

ChaNFS.lib Show annotated file Show diff for this revision Revisions of this file
ChaNFSSD.lib Show annotated file Show diff for this revision Revisions of this file
ConfigFile.lib Show annotated file Show diff for this revision Revisions of this file
DMX.lib Show annotated file Show diff for this revision Revisions of this file
DmxArtNet.lib Show annotated file Show diff for this revision Revisions of this file
EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
NEC950MHz.cpp Show annotated file Show diff for this revision Revisions of this file
NEC950MHz.h Show annotated file Show diff for this revision Revisions of this file
dbg.h Show annotated file Show diff for this revision Revisions of this file
dmx_patch.cpp Show annotated file Show diff for this revision Revisions of this file
dmx_patch.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChaNFS.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/NeoBelerophon/code/ChaNFS/#8ea634413549
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChaNFSSD.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/NeoBelerophon/code/ChaNFSSD/#7532f4c4163c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ConfigFile.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/ConfigFile/#f6ceafabe9f8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DMX.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/okini3939/code/DMX/#7826eb77d9ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DmxArtNet.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/okini3939/code/DmxArtNet/#c59dc374fc64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NEC950MHz.cpp	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,114 @@
+/*
+ * NEC 950MHz RF module
+ * H001-000003-001
+ */
+
+#include "mbed.h"
+#include "NEC950MHz.h"
+#include "dbg.h"
+#include <string.h>
+
+#define RXD p10
+#define TXD p9
+#define RST p12
+
+
+// host to network short
+#define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) )
+#define ntohs( x ) htons(x)
+// host to network long
+#define htonl( x ) ( (( (x) << 24 ) & 0xFF000000)  \
+                   | (( (x) <<  8 ) & 0x00FF0000)  \
+                   | (( (x) >>  8 ) & 0x0000FF00)  \
+                   | (( (x) >> 24 ) & 0x000000FF)  )
+#define ntohl( x ) htonl(x)
+
+
+static Serial rf(TXD, RXD);
+static DigitalOut rst(RST);
+
+int send_rf (int msgid, unsigned long dest, char *param, int len) {
+    int i;
+    static int msgno = 0;
+    struct ifMessage ifmsg;
+    unsigned char *buf = (unsigned char *)&ifmsg;
+
+    if (len > 240) len = 240;
+    msgno ++;
+    ifmsg.start = htons(0x0f5a);
+    ifmsg.length = 13 + len;
+    ifmsg.msgid = msgid;
+    ifmsg.msgno = msgno;
+    ifmsg.dstid = htonl(dest);
+    ifmsg.srcid = htonl(0xffffffff);
+    memcpy(ifmsg.parameter, param, len);
+    DBG("send_rf %d / %d\r\n", ifmsg.length, len);
+    
+    for (i = 0; i < ifmsg.length; i ++) {
+        rf.putc(buf[i]);
+    }
+
+    return ifmsg.msgno;
+}
+
+int read_rf (struct ifMessage *ifmsg) {
+    Timer timeout;
+    int i = 0, len = 0;
+    unsigned char buf[sizeof(struct ifMessage)];
+
+    timeout.start();
+    while (timeout.read_ms() < TIMEOUT) {
+        if (rf.readable()) {
+            buf[i] = rf.getc();
+            if (i == 0 && buf[i] == 0x0f) {
+                i ++;
+            } else
+            if (i == 1 && buf[i] == 0x5a) {
+                i ++;
+            } else
+            if (i == 2) {
+                len = buf[i];
+                i ++;
+            } else
+            if (i >= 3) {
+                i ++;
+                if (i >= len || i >= sizeof(buf)) break;
+            }
+            timeout.reset();
+        }
+    }
+    timeout.stop();
+ 
+    if (len) {
+        DBG("read_rf %d / %d\r\n", i, len);
+        memcpy(ifmsg, buf, len);
+    }
+    return len;
+}
+
+int init_rf (int ch) {
+    int no;
+    struct ifMessage ifmsg;
+    // high power, 100kbps, retry 0
+    char rfconf[] = {POWER_HIGH, ch, BAUD_100k, 1, 0, UART_115200, 1, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0x00, 0x00, 0x83, 0x41};
+    
+    rf.baud(38400);
+
+    rst = 0; // reset
+    wait_ms(50);
+    rst = 1;
+    wait_ms(100);
+
+    no = send_rf(MSGID_WRITE_CONFIG, 0xffffffff, rfconf, sizeof(rfconf));
+    DBG("rfconf %d\r\n", no);
+    // responce
+    if (! read_rf(&ifmsg) || ifmsg.msgid != MSGID_ACK || ifmsg.msgno != no) {
+        return -1;
+    }
+
+    rf.baud(115200);
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NEC950MHz.h	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,55 @@
+/*
+ * NEC 950MHz RF module
+ * H001-000003-001
+ */
+
+#include <inttypes.h>
+
+//#define CH 17 // 17-31
+#define TIMEOUT 10 // ms
+
+#define MSGID_ACK           0x00
+#define MSGID_NOACK         0x01
+#define MSGID_SEARCH        0x10
+#define MSGID_SEND_DAT      0x11
+#define MSGID_RESEND        0x12
+#define MSGID_SEND_NOACK    0x13
+#define MSGID_ENERGY_DETECT 0x16
+#define MSGID_SEND_CMD      0x17
+#define MSGID_WRITE_RFCONF  0x21
+#define MSGID_READ_RSSI     0x24
+#define MSGID_READ_CONFIG   0x29
+#define MSGID_WRITE_CONFIG  0x2A
+#define MSGID_READ_DEFAULT  0x7D
+#define MSGID_WRITE_DEFAULT 0x7E
+#define MSGID_RESET         0x77
+
+#define POWER_LOW           0x00
+#define POWER_MID           0x01
+#define POWER_HIGH          0x02
+
+#define BAUD_9600           0x02
+#define BAUD_50k            0x06
+#define BAUD_100k           0x07
+
+#define UART_4800           0x01
+#define UART_9600           0x02
+#define UART_19200          0x04
+#define UART_38400          0x05
+#define UART_56700          0x06
+#define UART_115200         0x08
+
+struct ifMessage {
+    uint16_t start;
+    uint8_t  length;
+    uint8_t  msgid;
+    uint8_t  msgno;
+    uint32_t dstid;
+    uint32_t srcid;
+    uint8_t  parameter[242];
+} __attribute__((packed));
+
+
+int send_rf (int msgid, unsigned long dest, char *param, int len);
+int read_rf (struct ifMessage *ifmsg);
+int init_rf (int ch);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg.h	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,7 @@
+//#define DEBUG
+
+#ifdef DEBUG 
+#define DBG(...) printf("" __VA_ARGS__) 
+#else 
+#define DBG(...) 
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmx_patch.cpp	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,132 @@
+/*
+ * DMX Station - mbed DMX Platform
+ * Copyright (c) 2012 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/*
+ * "patch#.csv" (#=dest port)
+ *  |dest ch,src port,src ch|
+ *
+ * dest port: 1=dmx out 1 / 2=dmx out 2 / 3=ArtNet 1 / 4=ArtNet 2 / 5=RF(NEC950MHz)
+ * src port: 1=dmx in 1 / 2=dmx in 2 / 3=ArtNet 1 / 4=ArtNet 2 / 5=UDP2DMX
+ */
+#include "dbg.h"
+#include "mbed.h"
+#include "SDFileSystem.h"
+#include "DmxArtNet.h"
+#include "DMX.h"
+#include "dmx_patch.h"
+
+
+SDFileSystem sd(p5, p6, p7, p8, "sd");
+
+struct TPatch dmx_patch[DEST_NUM][512] __attribute__((section("AHBSRAM0")));
+
+extern DmxArtNet art;
+extern DMX dmx1;
+extern DMX dmx2;
+
+extern volatile int patch_update;
+extern volatile int art_update[2];
+extern volatile int rf_update;
+extern char dmx_art[2][512];
+extern char dmx_udp[512];
+extern char dmx_rf[512];
+
+
+int load_patch () {
+    int i, j, dest, src, port;
+    FILE *fp;
+    char file[32];
+
+    for (i = 0; i < DEST_NUM; i ++) {
+        for (j = 0; j < 512; j ++) {
+            dmx_patch[i][j].port = i < 2 ? i + 2 : i - 2;
+            dmx_patch[i][j].addr = j;
+        }
+    }
+
+    if (sd.disk_initialize()) {
+        DBG("no SD\r\n");
+        return -1;
+    }
+
+    for (i = 0; i < DEST_NUM; i ++) {
+        sprintf(file, "/sd/patch%d.csv", i + 1);
+        fp = fopen(file, "r");
+        if (! fp) continue;
+        
+        while (1) {
+            // load csv
+            if (feof(fp)) break;
+            if (fscanf(fp, "%d,%d,%d", &dest, &port, &src) == 3) {
+                if (dest < 1 && dest > 512) continue;
+                if (src < 1 && src > 512) continue;
+                if (port < 1 && port > 5) continue;
+                dmx_patch[i][dest - 1].port = port - 1;
+                dmx_patch[i][dest - 1].addr = src - 1;
+                DBG("%d %d <- %d %d\r\n", i + 1, dest, port, src);
+            }
+        }
+        fclose(fp);
+    }
+    return 0;
+}
+
+void patch () {
+    int i, j, dmx;
+
+    for (i = 0; i < DEST_NUM; i ++) {
+        for (j = 0; j < 512; j ++) {
+            // src
+            switch (dmx_patch[i][j].port) {
+            case 0: // dmx in 1
+                dmx = dmx1.get(dmx_patch[i][j].addr);
+                break;
+            case 1: // dmx in 2
+                dmx = dmx2.get(dmx_patch[i][j].addr);
+                break;
+            case 2: // ArtNet 1
+                dmx = art.DmxIn[0][dmx_patch[i][j].addr];
+                break;
+            case 3: // ArtNet 2
+                dmx = art.DmxIn[1][dmx_patch[i][j].addr];
+                break;
+            case 4: // UDP2DMX
+                dmx = dmx_udp[dmx_patch[i][j].addr];
+                break;
+            default:
+                continue;
+            }
+            
+            // dest
+            switch (i) {
+            case 0: // dmx out 1
+                dmx1.put(j, dmx);
+                break;
+            case 1: // dmx out 2
+                dmx2.put(j, dmx);
+                break;
+            case 2: // ArtNet 1
+                if (dmx_art[0][j] != dmx) {
+                    dmx_art[0][j] = dmx;
+                    art_update[0] = 1;
+                }
+                break;
+            case 3: // ArtNet 2
+                if (dmx_art[1][j] != dmx) {
+                    dmx_art[1][j] = dmx;
+                    art_update[1] = 1;
+                }
+                break;
+            case 4: // RF(NEC950MHz)
+                if (dmx_rf[j] != dmx) {
+                    dmx_rf[j] = dmx;
+                    rf_update = 1;
+                }
+                break;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmx_patch.h	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,25 @@
+/*
+ * DMX Station - mbed DMX Platform
+ * Copyright (c) 2012 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#define DEST_NUM 5
+#define SRC_NUM 5
+/*
+#define DMX0 1
+#define DMX1 2
+#define ARTNET0 3
+#define ARTNET1 4
+#define RF 5
+#define CV2DMX 5
+*/
+struct TPatch {
+    short port;
+    short addr;
+};
+
+
+int load_patch ();
+void patch ();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,253 @@
+/*
+ * DMX Station - mbed DMX Platform
+ * Copyright (c) 2012 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief DMX Station
+ */
+
+/*
+ * "Node" Device
+ * "Universe" 512 DMX datas
+ * "Sub-Net" 16 Universe
+ * "Server" Controller
+ *
+ * can use over 40 Sub-Net on network.
+ */
+
+#include "dbg.h"
+#include "mbed.h"
+#include "EthernetNetIf.h"
+#include "DmxArtNet.h"
+#include "DMX.h"
+#include "NEC950MHz.h"
+#include "dmx_patch.h"
+
+#define LED_NET_ACT_ON led_yk = 0
+#define LED_NET_ACT_OFF led_yk = 1
+#define LED_NET_G_ON led_gayk = 1; led_gkya = 0
+#define LED_NET_Y_ON led_gayk = 0; led_gkya = 1
+#define LED_NET_GY_OFF led_gayk = 0; led_gkya = 0
+
+// for Touchable Fountains (Juco)
+#define UDP_PORT 10465
+#define RF_CH 31
+
+DigitalOut led_red(p22), led_yellow(p23);
+DigitalOut led_gayk(p24),led_gkya(p25), led_yk(p26);
+DigitalIn eth_link(P1_25), eth_speed(P1_26);
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+EthernetNetIf *eth;
+Serial pc(USBTX, USBRX);
+
+DmxArtNet art;
+DMX dmx1(p13, p14);
+DMX dmx2(p28, p27);
+
+UDPSocket udp;
+
+volatile int patch_update = 0;
+volatile int art_update[2] = {0, 0};
+volatile int rf_update = 0, rf_flg = 0;
+char dmx_art[2][512] __attribute__((section("AHBSRAM0")));
+char dmx_udp[512] __attribute__((section("AHBSRAM0")));
+char dmx_rf[512] __attribute__((section("AHBSRAM0")));
+
+
+extern "C" void mbed_mac_address(char *s);
+
+void no_memory () {
+    led_red = 1;
+    printf("panic: can't allocate to memory!\r\n");
+    exit(-1);
+}
+
+void shutdown () {
+    art.ArtPollReply.NumPorts = 0;
+    strcpy(art.ArtPollReply.NodeReport, "Shutdown");
+    art.SendArtPollReply();
+    art.Done();
+}
+
+void isr_udp (UDPSocketEvent e) {
+    int len;
+    Host remote;
+
+    if (e == UDPSOCKET_READABLE) {
+        // UDP2DMX
+        LED_NET_ACT_ON;
+        led_yellow = 1;
+        led3 = 1;
+        len = udp.recvfrom((char*)dmx_udp, sizeof(dmx_udp), &remote);
+        DBG("recv udp %d\r\n", len);
+        patch_update = 5;
+    }
+}
+
+void isr_timer () {
+    led_yellow = 0;
+    LED_NET_ACT_OFF;
+    led1 = 0; led2 = 0; led3 = 0; led4 = 0;
+}
+
+int init_artnet (IpAddr *ip) {
+    char mac[6];
+    EthernetErr ethErr;
+
+    eth_link.mode(PullUp);
+    eth_speed.mode(PullUp);
+
+    if (! eth_link) {
+        LED_NET_G_ON;
+    }
+    LED_NET_ACT_ON;
+
+    // create ip address from mac address
+    mbed_mac_address(mac);
+    *ip = IpAddr(2, mac[3], mac[4], mac[5]);
+    eth = new EthernetNetIf(*ip, IpAddr(255,0,0,0), IpAddr(0,0,0,0), IpAddr(0,0,0,0));
+    ethErr = eth->setup();
+    if (ethErr) {
+        LED_NET_Y_ON;
+        led_red = 1;
+        return -1;
+    }
+
+    wait(2);
+
+    // init ArtNet
+    art.BindIpAddress = *ip;
+    art.BCastAddress = IpAddr(2,255,255,255);
+
+    art.InitArtPollReplyDefaults();
+    // Device
+    art.ArtPollReply.PortType[0] = 128; // output
+    art.ArtPollReply.PortType[1] = 128; // output
+    art.ArtPollReply.PortType[2] = 64; // input
+    art.ArtPollReply.GoodInput[2] = 4;
+    art.ArtPollReply.PortType[3] = 64; // input
+    art.ArtPollReply.GoodInput[3] = 4;
+
+    art.Init();
+    art.SendArtPollReply(); // announce to art-net nodes
+
+    pc.printf("init ArtNet\r\n");
+    return 0;
+}
+
+int main () {
+    int i;
+    Ticker timer;
+    ifMessage ifmsg;
+    IpAddr ip;
+    UDPSocketErr udpErr;
+
+    set_new_handler(no_memory); // new handler function
+
+    pc.baud(112500);
+    
+    memset(dmx_art, 0, sizeof(dmx_art));
+    memset(dmx_udp, 0, sizeof(dmx_udp));
+    memset(dmx_rf, 0, sizeof(dmx_rf));
+
+    load_patch();
+    timer.attach(&isr_timer, 0.1);
+
+    // init ArtNet
+    if (init_artnet(&ip)) return -1;
+    pc.printf("Bind to interface: %d.%d.%d.%d\r\n", (unsigned char)ip[0], (unsigned char)ip[1], (unsigned char)ip[2], (unsigned char)ip[3]);
+
+    // init UDP2DMX
+    udpErr = udp.bind(Host(ip, UDP_PORT, NULL));
+    if (udpErr) {
+        pc.printf("Bind error (udp2dmx)\r\n");
+        return -1;
+    }
+    udp.setOnEvent(&isr_udp);
+    pc.printf("init UDP2DMX\r\n");
+
+    // init NEC950MHz
+    if (! init_rf(RF_CH)) {
+        pc.printf("init RF\r\n");
+    }
+
+    pc.printf("ArtNode begin\r\n");
+
+    for (;;) {
+        Net::poll();
+
+        if (! eth_link) {
+            LED_NET_G_ON;
+        } else {
+            LED_NET_GY_OFF;
+        }
+
+        if (dmx1.is_recived) {
+            // dmx in 1
+            LED_NET_ACT_ON;
+            led_yellow = 1;
+            led1 = 1;
+            patch_update = 1;
+            dmx1.is_recived = 1;
+            DBG("recv, dmx 1\r\n");
+        }
+
+        if (dmx2.is_recived) {
+            // dmx in 2
+            LED_NET_ACT_ON;
+            led_yellow = 1;
+            led1 = 1;
+            patch_update = 2;
+            dmx2.is_recived = 2;
+            DBG("recv, dmx 2\r\n");
+        }
+
+        if (art.Work()) {
+            // ArtNet
+            LED_NET_ACT_ON;
+            led_yellow = 1;
+            led2 = 1;
+            patch_update = art.LastRecievedUniverse + 3;
+            DBG("recv, node %d\r\n", art.LastRecievedUniverse + 1);
+        }
+
+        if (patch_update) {
+            // update DMX patch
+            led4 = 1;
+            patch();
+            DBG("update");
+        
+            for (i = 0; i < 2; i ++) {
+                // ArtNet good status
+                if (art_update[i]) {
+                    DBG("art good");
+                    Net::poll();
+                    art.ArtPollReply.GoodInput[i] = 128;
+                    art.Send_ArtDmx(i, 0, dmx_art[i], 512);
+                    art_update[i] = 0;
+                }
+            }
+
+            if (! rf_flg && rf_update) {
+                // RF send
+                send_rf(MSGID_SEND_NOACK, 0xffffffff, dmx_rf, 200);
+                rf_flg = 1;
+                rf_update = 0;
+            }
+
+            patch_update = 0;
+        }
+
+        if (rf_flg && read_rf(&ifmsg) > 0) {
+            // RF responce
+            DBG("recv %d\r\n", ifmsg.msgid);
+            if (ifmsg.msgid != MSGID_ACK) {
+                DBG("no ack\r\n");
+            }
+            rf_flg = 0;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Mar 01 01:40:07 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/4c0c40fd0593