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

main.cpp

Committer:
okini3939
Date:
2012-03-01
Revision:
0:41b699bbda83

File content as of revision 0:41b699bbda83:

/*
 * 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;
        }
    }
}