http://mbed.org/users/okini3939/notebook/art-net/
Dependents: ArtNode ArtNode DMXStation ArtNodeLED ... more
DmxArtNet.cpp
- Committer:
- okini3939
- Date:
- 2011-09-29
- Revision:
- 1:c59dc374fc64
- Parent:
- 0:629617d401de
- Child:
- 2:0753f1ed1dec
File content as of revision 1:c59dc374fc64:
/* * Control Art-Net from freepascal & delphi * (c) Rowan Maclachlan (hippy) rowanmac@optusnet.com.au [15d/01m/06y] * * Free for personal not-for-profit use only, please contact me if you are * using it in a commercial product, as i would like a copy :) * * http://members.westnet.com.au/rowanmac/ * * for mbed port by Suga 2011 */ /** @file */ #include "mbed.h" #include "EthernetNetIf.h" #include "UDPSocket.h" #include "DmxArtNet.h" #include "dbg.h" #include <stdio.h> #include <string.h> // 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) extern "C" void mbed_mac_address(char *s); // function to make a word (16bit) from two bytes (2 x 8bit) int DmxArtNet::makeword16 (int lsb, int msb) { return (msb << 8) + lsb; } // report a socket error, halt program void DmxArtNet::SocketErrorOccured (char *proc) { LError = 1; snprintf(LErrorString, sizeof(LErrorString), "socket> error occured in '%s'\r\n", proc); DBG("%s", LErrorString); } // clear error void DmxArtNet::ClearError () { LError = 0; } int DmxArtNet::Init () { int i; UDPSocketErr err; LError = 0; // no error yet :) Init_ArtDMX(); // initialize ArtDmx structure // art = new UDPSocket; // create socket net_loopback = 0; // dont listen to ourself, default rxlen = 0; if (BindIpAddress == IpAddr(0,0,0,0)) { BindIpAddress = IpAddr(2,0,0,1); // default to 2.0.0.1 } err = _art.bind(Host(BindIpAddress, ArtUDPPort, NULL)); if (err) { SocketErrorOccured("Bind error"); return -1; } if (BCastAddress == IpAddr(0,0,0,0)) { BCastAddress = IpAddr(2,255,255,255); // default } RemoteSin = Host(BCastAddress, ArtUDPPort, NULL); for (i = 0; i < ArtMaxUniv; i ++) { DmxIn[i] = new unsigned char[512]; } _art.setOnEvent(this, &DmxArtNet::on_UDPSocketEvent); return 0; } void DmxArtNet::on_UDPSocketEvent (UDPSocketEvent e) { if (e == UDPSOCKET_READABLE) { rxlen = _art.recvfrom((char*)buf, sizeof(buf), &RemoteSin); } } int DmxArtNet::Work() { // int rxlen, pos; int pos; int x, y; unsigned char *RecvByte; if (rxlen >= sizeof(ArtPacketHeader)) { // retreive the packet header // err = art.Recv(buf, sizeof(ArtPacketHeader), 10); // if looback disabled if (!net_loopback && RemoteSin.getIp() == BindIpAddress) { DBG("ArtNet> loopback detected\r\n"); // art.purge; // dump the data rxlen = 0; return 0; // don't read packets // which we sent! } DBG("ArtNet> RX: %d\r\n", rxlen); memcpy(&ArtHead, buf, sizeof(ArtPacketHeader)); // confirm is vaild art-net packet if (strncmp(ArtHead.ID, ArtHeaderID, 8) == 0) { RecvByte = &buf[10]; switch (ArtHead.OpCode) { // determine packet type case OP_Output: // An ArtDMX Packet, containts dmx universe ArtDMX.VersionH = RecvByte[0]; ArtDMX.Version = RecvByte[1]; ArtDMX.Sequence = RecvByte[2]; ArtDMX.Physical = RecvByte[3]; x = RecvByte[4]; y = RecvByte[5]; ArtDMX.Universes = makeword16(x,y); LastRecievedUniverse = ArtDMX.Universes; x = RecvByte[6]; y = RecvByte[7]; ArtDMX.Length = makeword16(y,x); // check data length if (ArtDMX.Length <= 512) { // get the dmx data for (pos = 0; pos < ArtDMX.Length; pos ++) { DmxIn[ArtDMX.Universes][pos] = RecvByte[8 + pos]; } DBG(" <Art-Dmx> Size: %d Univ: %d Ch1: %d\r\n", ArtDMX.Length, ArtDMX.Universes, DmxIn[ArtDMX.Universes][0]); rxlen = 0; return 1; // something happened! } break; // op_output case OP_Poll: ArtPoll.VersionH = RecvByte[0]; ArtPoll.Version = RecvByte[1]; ArtPoll.TalkToMe = RecvByte[2]; DBG(" <Art-Poll> Ver: %d TalkToMe: %d\r\n", ArtPoll.Version, ArtPoll.TalkToMe); SendArtPollReply(); // send a reply to the ArtPoll break; default: // NYI Packet Type break; } // case packet type } // waiting data } rxlen = 0; return 0; } // socket shutdown void DmxArtNet::Done () { _art.resetOnEvent(); _art.close(); } // init ArtDMX packet void DmxArtNet::Init_ArtDMX () { // header stuff memcpy(ArtDMX.ID, ArtHeaderID, 8); ArtDMX.OpCode = OP_Output; ArtDMX.Version = ArtVersion; // dmx stuff ArtDMX.Universes = 0; // this is the destination for the dmx ArtDMX.Sequence = 0; ArtDMX.Length = htons(512); } // send ArtDmx Packet int DmxArtNet::Send_ArtDmx(int univ, int physical, char *data, int length) { Host Remote; // build a artdmx packet memcpy(ArtDMX.Data, data, length); ArtDMX.Universes = univ; ArtDMX.Length = htons(length); ArtDMX.Physical = physical; ArtDMX.Sequence ++; // set place to send Remote = Host(BCastAddress, ArtUDPPort, NULL); // send it off _art.sendto((char*)&ArtDMX, sizeof(ArtDMX), &Remote); return 0; } void DmxArtNet::InitArtPollReplyDefaults () { memcpy(ArtPollReply.ID, ArtHeaderID, 8); ArtPollReply.OpCode = OP_PollReply; // reply packet ArtPollReply.Version = ArtVersion; memcpy(&ArtPollReply.Addr, &localaddr, sizeof(localaddr)); strncpy(ArtPollReply.ShortName, STR_ShortName, 18); strncpy(ArtPollReply.LongName, STR_LongName, 64); strncpy(ArtPollReply.NodeReport, "OK", 64); ArtPollReply.Style = StyleNode; mbed_mac_address((char*)&ArtPollReply.Mac); ArtPollReply.NumPortsH = 0; ArtPollReply.NumPorts = 0; ArtPollReply.Swout[0] = 0; ArtPollReply.Swout[1] = 0; ArtPollReply.Swout[2] = 0; ArtPollReply.Swout[3] = 0; ArtPollReply.Swin[0] = 0; ArtPollReply.Swin[1] = 0; ArtPollReply.Swin[2] = 0; ArtPollReply.Swin[3] = 0; ArtPollReply.GoodOutput[0] = 0; ArtPollReply.GoodOutput[1] = 0; ArtPollReply.GoodOutput[2] = 0; ArtPollReply.GoodOutput[3] = 0; ArtPollReply.PortType[0] = 255; ArtPollReply.PortType[1] = 255; ArtPollReply.PortType[2] = 255; ArtPollReply.PortType[3] = 255; } // send ArtPoll Reply int DmxArtNet::SendArtPollReply () { // send the packet _art.sendto((char*)&ArtPollReply, sizeof(ArtPollReply), &RemoteSin); return 0; }