http://mbed.org/users/okini3939/notebook/art-net/

Dependents:   ArtNode ArtNode DMXStation ArtNodeLED ... more

Committer:
okini3939
Date:
Thu Sep 29 15:46:43 2011 +0000
Revision:
0:629617d401de
Child:
1:c59dc374fc64

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:629617d401de 1 /*
okini3939 0:629617d401de 2 * Control Art-Net from freepascal & delphi
okini3939 0:629617d401de 3 * (c) Rowan Maclachlan (hippy) rowanmac@optusnet.com.au [15d/01m/06y]
okini3939 0:629617d401de 4 *
okini3939 0:629617d401de 5 * Free for personal not-for-profit use only, please contact me if you are
okini3939 0:629617d401de 6 * using it in a commercial product, as i would like a copy :)
okini3939 0:629617d401de 7 *
okini3939 0:629617d401de 8 * http://members.westnet.com.au/rowanmac/
okini3939 0:629617d401de 9 *
okini3939 0:629617d401de 10 * for mbed port by Suga 2011
okini3939 0:629617d401de 11 */
okini3939 0:629617d401de 12
okini3939 0:629617d401de 13 /** @file
okini3939 0:629617d401de 14 */
okini3939 0:629617d401de 15
okini3939 0:629617d401de 16 #include "mbed.h"
okini3939 0:629617d401de 17 #include "EthernetNetIf.h"
okini3939 0:629617d401de 18 #include "UDPSocket.h"
okini3939 0:629617d401de 19 #include "DmxArtNet.h"
okini3939 0:629617d401de 20 #include "dbg.h"
okini3939 0:629617d401de 21 #include <stdio.h>
okini3939 0:629617d401de 22 #include <string.h>
okini3939 0:629617d401de 23
okini3939 0:629617d401de 24 // host to network short
okini3939 0:629617d401de 25 #define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) )
okini3939 0:629617d401de 26 #define ntohs( x ) htons(x)
okini3939 0:629617d401de 27 // host to network long
okini3939 0:629617d401de 28 #define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \
okini3939 0:629617d401de 29 | (( (x) << 8 ) & 0x00FF0000) \
okini3939 0:629617d401de 30 | (( (x) >> 8 ) & 0x0000FF00) \
okini3939 0:629617d401de 31 | (( (x) >> 24 ) & 0x000000FF) )
okini3939 0:629617d401de 32 #define ntohl( x ) htonl(x)
okini3939 0:629617d401de 33
okini3939 0:629617d401de 34
okini3939 0:629617d401de 35 extern "C" void mbed_mac_address(char *s);
okini3939 0:629617d401de 36
okini3939 0:629617d401de 37
okini3939 0:629617d401de 38 // function to make a word (16bit) from two bytes (2 x 8bit)
okini3939 0:629617d401de 39 int DmxArtNet::makeword16 (int lsb, int msb) {
okini3939 0:629617d401de 40 return (msb << 8) + lsb;
okini3939 0:629617d401de 41 }
okini3939 0:629617d401de 42
okini3939 0:629617d401de 43 // report a socket error, halt program
okini3939 0:629617d401de 44 void DmxArtNet::SocketErrorOccured (char *proc) {
okini3939 0:629617d401de 45 LError = 1;
okini3939 0:629617d401de 46 snprintf(LErrorString, sizeof(LErrorString), "socket> error occured in '%s'\r\n", proc);
okini3939 0:629617d401de 47 DBG("%s", LErrorString);
okini3939 0:629617d401de 48 }
okini3939 0:629617d401de 49
okini3939 0:629617d401de 50 // clear error
okini3939 0:629617d401de 51 void DmxArtNet::ClearError () {
okini3939 0:629617d401de 52 LError = 0;
okini3939 0:629617d401de 53 }
okini3939 0:629617d401de 54
okini3939 0:629617d401de 55 int DmxArtNet::Init () {
okini3939 0:629617d401de 56 int i;
okini3939 0:629617d401de 57 UDPSocketErr err;
okini3939 0:629617d401de 58
okini3939 0:629617d401de 59 LError = 0; // no error yet :)
okini3939 0:629617d401de 60 Init_ArtDMX(); // initialize ArtDmx structure
okini3939 0:629617d401de 61 // art = new UDPSocket; // create socket
okini3939 0:629617d401de 62 net_loopback = 0; // dont listen to ourself, default
okini3939 0:629617d401de 63 rxlen = 0;
okini3939 0:629617d401de 64
okini3939 0:629617d401de 65 if (BindIpAddress == IpAddr(0,0,0,0)) {
okini3939 0:629617d401de 66 BindIpAddress = IpAddr(2,0,0,1); // default to 2.0.0.1
okini3939 0:629617d401de 67 }
okini3939 0:629617d401de 68 err = _art.bind(Host(BindIpAddress, ArtUDPPort, NULL));
okini3939 0:629617d401de 69 if (err) {
okini3939 0:629617d401de 70 SocketErrorOccured("Bind error");
okini3939 0:629617d401de 71 return -1;
okini3939 0:629617d401de 72 }
okini3939 0:629617d401de 73 if (BCastAddress == IpAddr(0,0,0,0)) {
okini3939 0:629617d401de 74 BCastAddress = IpAddr(2,255,255,255); // default
okini3939 0:629617d401de 75 }
okini3939 0:629617d401de 76 RemoteSin = Host(BCastAddress, ArtUDPPort, NULL);
okini3939 0:629617d401de 77
okini3939 0:629617d401de 78 for (i = 0; i < ArtMaxUniv; i ++) {
okini3939 0:629617d401de 79 DmxIn[i] = new unsigned char[512];
okini3939 0:629617d401de 80 }
okini3939 0:629617d401de 81
okini3939 0:629617d401de 82 _art.setOnEvent(this, &DmxArtNet::on_UDPSocketEvent);
okini3939 0:629617d401de 83
okini3939 0:629617d401de 84 return 0;
okini3939 0:629617d401de 85 }
okini3939 0:629617d401de 86
okini3939 0:629617d401de 87 void DmxArtNet::on_UDPSocketEvent (UDPSocketEvent e) {
okini3939 0:629617d401de 88 if (e == UDPSOCKET_READABLE) {
okini3939 0:629617d401de 89 rxlen = _art.recvfrom((char*)buf, sizeof(buf), &RemoteSin);
okini3939 0:629617d401de 90 }
okini3939 0:629617d401de 91 }
okini3939 0:629617d401de 92
okini3939 0:629617d401de 93 int DmxArtNet::Work() {
okini3939 0:629617d401de 94 // int rxlen, pos;
okini3939 0:629617d401de 95 int pos;
okini3939 0:629617d401de 96 int x, y;
okini3939 0:629617d401de 97 int err;
okini3939 0:629617d401de 98 unsigned char *RecvByte;
okini3939 0:629617d401de 99
okini3939 0:629617d401de 100 if (rxlen >= sizeof(ArtPacketHeader)) {
okini3939 0:629617d401de 101 // retreive the packet header
okini3939 0:629617d401de 102 // err = art.Recv(buf, sizeof(ArtPacketHeader), 10);
okini3939 0:629617d401de 103
okini3939 0:629617d401de 104 // if looback disabled
okini3939 0:629617d401de 105 if (!net_loopback && RemoteSin.getIp() == BindIpAddress) {
okini3939 0:629617d401de 106 DBG("ArtNet> loopback detected\r\n");
okini3939 0:629617d401de 107
okini3939 0:629617d401de 108 // art.purge; // dump the data
okini3939 0:629617d401de 109 rxlen = 0;
okini3939 0:629617d401de 110 return 0; // don't read packets
okini3939 0:629617d401de 111 // which we sent!
okini3939 0:629617d401de 112 }
okini3939 0:629617d401de 113
okini3939 0:629617d401de 114 DBG("ArtNet> RX: %d\r\n", rxlen);
okini3939 0:629617d401de 115 memcpy(&ArtHead, buf, sizeof(ArtPacketHeader));
okini3939 0:629617d401de 116
okini3939 0:629617d401de 117 // confirm is vaild art-net packet
okini3939 0:629617d401de 118 if (strncmp(ArtHead.ID, ArtHeaderID, 8) == 0) {
okini3939 0:629617d401de 119
okini3939 0:629617d401de 120 RecvByte = &buf[10];
okini3939 0:629617d401de 121
okini3939 0:629617d401de 122 switch (ArtHead.OpCode) { // determine packet type
okini3939 0:629617d401de 123
okini3939 0:629617d401de 124 case OP_Output: // An ArtDMX Packet, containts dmx universe
okini3939 0:629617d401de 125 ArtDMX.VersionH = RecvByte[0];
okini3939 0:629617d401de 126 ArtDMX.Version = RecvByte[1];
okini3939 0:629617d401de 127 ArtDMX.Sequence = RecvByte[2];
okini3939 0:629617d401de 128 ArtDMX.Physical = RecvByte[3];
okini3939 0:629617d401de 129
okini3939 0:629617d401de 130 x = RecvByte[4];
okini3939 0:629617d401de 131 y = RecvByte[5];
okini3939 0:629617d401de 132 ArtDMX.Universes = makeword16(x,y);
okini3939 0:629617d401de 133 LastRecievedUniverse = ArtDMX.Universes;
okini3939 0:629617d401de 134
okini3939 0:629617d401de 135 x = RecvByte[6];
okini3939 0:629617d401de 136 y = RecvByte[7];
okini3939 0:629617d401de 137 ArtDMX.Length = makeword16(y,x);
okini3939 0:629617d401de 138
okini3939 0:629617d401de 139 // check data length
okini3939 0:629617d401de 140 if (ArtDMX.Length <= 512) {
okini3939 0:629617d401de 141 // get the dmx data
okini3939 0:629617d401de 142 for (pos = 0; pos < ArtDMX.Length; pos ++) {
okini3939 0:629617d401de 143 DmxIn[ArtDMX.Universes][pos] = RecvByte[8 + pos];
okini3939 0:629617d401de 144 }
okini3939 0:629617d401de 145 DBG(" <Art-Dmx> Size: %d Univ: %d Ch1: %d\r\n", ArtDMX.Length, ArtDMX.Universes, DmxIn[ArtDMX.Universes][0]);
okini3939 0:629617d401de 146 return 0; // something happened!
okini3939 0:629617d401de 147 }
okini3939 0:629617d401de 148 break; // op_output
okini3939 0:629617d401de 149
okini3939 0:629617d401de 150 case OP_Poll:
okini3939 0:629617d401de 151 ArtPoll.VersionH = RecvByte[0];
okini3939 0:629617d401de 152 ArtPoll.Version = RecvByte[1];
okini3939 0:629617d401de 153 ArtPoll.TalkToMe = RecvByte[2];
okini3939 0:629617d401de 154 DBG(" <Art-Poll> Ver: %d TalkToMe: %d\r\n", ArtPoll.Version, ArtPoll.TalkToMe);
okini3939 0:629617d401de 155 SendArtPollReply(); // send a reply to the ArtPoll
okini3939 0:629617d401de 156 break;
okini3939 0:629617d401de 157
okini3939 0:629617d401de 158 default:
okini3939 0:629617d401de 159 // NYI Packet Type
okini3939 0:629617d401de 160 break;
okini3939 0:629617d401de 161 } // case packet type
okini3939 0:629617d401de 162
okini3939 0:629617d401de 163 rxlen = 0;
okini3939 0:629617d401de 164 return 1;
okini3939 0:629617d401de 165 } // waiting data
okini3939 0:629617d401de 166 }
okini3939 0:629617d401de 167
okini3939 0:629617d401de 168 rxlen = 0;
okini3939 0:629617d401de 169 return 0;
okini3939 0:629617d401de 170 }
okini3939 0:629617d401de 171
okini3939 0:629617d401de 172 // socket shutdown
okini3939 0:629617d401de 173 void DmxArtNet::Done () {
okini3939 0:629617d401de 174 _art.resetOnEvent();
okini3939 0:629617d401de 175 _art.close();
okini3939 0:629617d401de 176 }
okini3939 0:629617d401de 177
okini3939 0:629617d401de 178 // init ArtDMX packet
okini3939 0:629617d401de 179 void DmxArtNet::Init_ArtDMX () {
okini3939 0:629617d401de 180 // header stuff
okini3939 0:629617d401de 181 memcpy(ArtDMX.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 182 ArtDMX.OpCode = OP_Output;
okini3939 0:629617d401de 183 ArtDMX.Version = ArtVersion;
okini3939 0:629617d401de 184 // dmx stuff
okini3939 0:629617d401de 185 ArtDMX.Universes = 0; // this is the destination for the dmx
okini3939 0:629617d401de 186 ArtDMX.Sequence = 0;
okini3939 0:629617d401de 187 ArtDMX.Length = htons(512);
okini3939 0:629617d401de 188 }
okini3939 0:629617d401de 189
okini3939 0:629617d401de 190 // send ArtDmx Packet
okini3939 0:629617d401de 191 int DmxArtNet::Send_ArtDmx(int univ, int physical, char *data, int length) {
okini3939 0:629617d401de 192 Host Remote;
okini3939 0:629617d401de 193
okini3939 0:629617d401de 194 // build a artdmx packet
okini3939 0:629617d401de 195 memcpy(ArtDMX.Data, data, length);
okini3939 0:629617d401de 196 ArtDMX.Universes = univ;
okini3939 0:629617d401de 197 ArtDMX.Length = htons(length);
okini3939 0:629617d401de 198 ArtDMX.Physical = physical;
okini3939 0:629617d401de 199 ArtDMX.Sequence ++;
okini3939 0:629617d401de 200
okini3939 0:629617d401de 201 // set place to send
okini3939 0:629617d401de 202 Remote = Host(BCastAddress, ArtUDPPort, NULL);
okini3939 0:629617d401de 203
okini3939 0:629617d401de 204 // send it off
okini3939 0:629617d401de 205 _art.sendto((char*)&ArtDMX, sizeof(ArtDMX), &Remote);
okini3939 0:629617d401de 206
okini3939 0:629617d401de 207 return 0;
okini3939 0:629617d401de 208 }
okini3939 0:629617d401de 209
okini3939 0:629617d401de 210
okini3939 0:629617d401de 211
okini3939 0:629617d401de 212 void DmxArtNet::InitArtPollReplyDefaults () {
okini3939 0:629617d401de 213 memcpy(ArtPollReply.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 214 ArtPollReply.OpCode = OP_PollReply; // reply packet
okini3939 0:629617d401de 215 ArtPollReply.Version = ArtVersion;
okini3939 0:629617d401de 216
okini3939 0:629617d401de 217 memcpy(&ArtPollReply.Addr, &localaddr, sizeof(localaddr));
okini3939 0:629617d401de 218 strncpy(ArtPollReply.ShortName, STR_ShortName, 18);
okini3939 0:629617d401de 219 strncpy(ArtPollReply.LongName, STR_LongName, 64);
okini3939 0:629617d401de 220 strncpy(ArtPollReply.NodeReport, "OK", 64);
okini3939 0:629617d401de 221 ArtPollReply.Style = StyleNode;
okini3939 0:629617d401de 222
okini3939 0:629617d401de 223 mbed_mac_address((char*)&ArtPollReply.Mac);
okini3939 0:629617d401de 224
okini3939 0:629617d401de 225 ArtPollReply.NumPortsH = 0;
okini3939 0:629617d401de 226 ArtPollReply.NumPorts = 0;
okini3939 0:629617d401de 227 ArtPollReply.Swout[0] = 0;
okini3939 0:629617d401de 228 ArtPollReply.Swout[1] = 0;
okini3939 0:629617d401de 229 ArtPollReply.Swout[2] = 0;
okini3939 0:629617d401de 230 ArtPollReply.Swout[3] = 0;
okini3939 0:629617d401de 231 ArtPollReply.Swin[0] = 0;
okini3939 0:629617d401de 232 ArtPollReply.Swin[1] = 0;
okini3939 0:629617d401de 233 ArtPollReply.Swin[2] = 0;
okini3939 0:629617d401de 234 ArtPollReply.Swin[3] = 0;
okini3939 0:629617d401de 235
okini3939 0:629617d401de 236 ArtPollReply.GoodOutput[0] = 0;
okini3939 0:629617d401de 237 ArtPollReply.GoodOutput[1] = 0;
okini3939 0:629617d401de 238 ArtPollReply.GoodOutput[2] = 0;
okini3939 0:629617d401de 239 ArtPollReply.GoodOutput[3] = 0;
okini3939 0:629617d401de 240 ArtPollReply.PortType[0] = 255;
okini3939 0:629617d401de 241 ArtPollReply.PortType[1] = 255;
okini3939 0:629617d401de 242 ArtPollReply.PortType[2] = 255;
okini3939 0:629617d401de 243 ArtPollReply.PortType[3] = 255;
okini3939 0:629617d401de 244 }
okini3939 0:629617d401de 245
okini3939 0:629617d401de 246 // send ArtPoll Reply
okini3939 0:629617d401de 247 int DmxArtNet::SendArtPollReply () {
okini3939 0:629617d401de 248
okini3939 0:629617d401de 249 // send the packet
okini3939 0:629617d401de 250 _art.sendto((char*)&ArtPollReply, sizeof(ArtPollReply), &RemoteSin);
okini3939 0:629617d401de 251
okini3939 0:629617d401de 252 return 0;
okini3939 0:629617d401de 253 }