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

Dependents:   ArtNode ArtNode DMXStation ArtNodeLED ... more

Committer:
okini3939
Date:
Thu Sep 29 16:42:34 2011 +0000
Revision:
1:c59dc374fc64
Parent:
0:629617d401de
Child:
2:0753f1ed1dec

        

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 unsigned char *RecvByte;
okini3939 0:629617d401de 98
okini3939 0:629617d401de 99 if (rxlen >= sizeof(ArtPacketHeader)) {
okini3939 0:629617d401de 100 // retreive the packet header
okini3939 0:629617d401de 101 // err = art.Recv(buf, sizeof(ArtPacketHeader), 10);
okini3939 0:629617d401de 102
okini3939 0:629617d401de 103 // if looback disabled
okini3939 0:629617d401de 104 if (!net_loopback && RemoteSin.getIp() == BindIpAddress) {
okini3939 0:629617d401de 105 DBG("ArtNet> loopback detected\r\n");
okini3939 0:629617d401de 106
okini3939 0:629617d401de 107 // art.purge; // dump the data
okini3939 0:629617d401de 108 rxlen = 0;
okini3939 0:629617d401de 109 return 0; // don't read packets
okini3939 0:629617d401de 110 // which we sent!
okini3939 0:629617d401de 111 }
okini3939 0:629617d401de 112
okini3939 0:629617d401de 113 DBG("ArtNet> RX: %d\r\n", rxlen);
okini3939 0:629617d401de 114 memcpy(&ArtHead, buf, sizeof(ArtPacketHeader));
okini3939 0:629617d401de 115
okini3939 0:629617d401de 116 // confirm is vaild art-net packet
okini3939 0:629617d401de 117 if (strncmp(ArtHead.ID, ArtHeaderID, 8) == 0) {
okini3939 0:629617d401de 118
okini3939 0:629617d401de 119 RecvByte = &buf[10];
okini3939 0:629617d401de 120
okini3939 0:629617d401de 121 switch (ArtHead.OpCode) { // determine packet type
okini3939 0:629617d401de 122
okini3939 0:629617d401de 123 case OP_Output: // An ArtDMX Packet, containts dmx universe
okini3939 0:629617d401de 124 ArtDMX.VersionH = RecvByte[0];
okini3939 0:629617d401de 125 ArtDMX.Version = RecvByte[1];
okini3939 0:629617d401de 126 ArtDMX.Sequence = RecvByte[2];
okini3939 0:629617d401de 127 ArtDMX.Physical = RecvByte[3];
okini3939 0:629617d401de 128
okini3939 0:629617d401de 129 x = RecvByte[4];
okini3939 0:629617d401de 130 y = RecvByte[5];
okini3939 0:629617d401de 131 ArtDMX.Universes = makeword16(x,y);
okini3939 0:629617d401de 132 LastRecievedUniverse = ArtDMX.Universes;
okini3939 0:629617d401de 133
okini3939 0:629617d401de 134 x = RecvByte[6];
okini3939 0:629617d401de 135 y = RecvByte[7];
okini3939 0:629617d401de 136 ArtDMX.Length = makeword16(y,x);
okini3939 0:629617d401de 137
okini3939 0:629617d401de 138 // check data length
okini3939 0:629617d401de 139 if (ArtDMX.Length <= 512) {
okini3939 0:629617d401de 140 // get the dmx data
okini3939 0:629617d401de 141 for (pos = 0; pos < ArtDMX.Length; pos ++) {
okini3939 0:629617d401de 142 DmxIn[ArtDMX.Universes][pos] = RecvByte[8 + pos];
okini3939 0:629617d401de 143 }
okini3939 0:629617d401de 144 DBG(" <Art-Dmx> Size: %d Univ: %d Ch1: %d\r\n", ArtDMX.Length, ArtDMX.Universes, DmxIn[ArtDMX.Universes][0]);
okini3939 1:c59dc374fc64 145 rxlen = 0;
okini3939 1:c59dc374fc64 146 return 1; // 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 } // waiting data
okini3939 0:629617d401de 163 }
okini3939 0:629617d401de 164
okini3939 0:629617d401de 165 rxlen = 0;
okini3939 0:629617d401de 166 return 0;
okini3939 0:629617d401de 167 }
okini3939 0:629617d401de 168
okini3939 0:629617d401de 169 // socket shutdown
okini3939 0:629617d401de 170 void DmxArtNet::Done () {
okini3939 0:629617d401de 171 _art.resetOnEvent();
okini3939 0:629617d401de 172 _art.close();
okini3939 0:629617d401de 173 }
okini3939 0:629617d401de 174
okini3939 0:629617d401de 175 // init ArtDMX packet
okini3939 0:629617d401de 176 void DmxArtNet::Init_ArtDMX () {
okini3939 0:629617d401de 177 // header stuff
okini3939 0:629617d401de 178 memcpy(ArtDMX.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 179 ArtDMX.OpCode = OP_Output;
okini3939 0:629617d401de 180 ArtDMX.Version = ArtVersion;
okini3939 0:629617d401de 181 // dmx stuff
okini3939 0:629617d401de 182 ArtDMX.Universes = 0; // this is the destination for the dmx
okini3939 0:629617d401de 183 ArtDMX.Sequence = 0;
okini3939 0:629617d401de 184 ArtDMX.Length = htons(512);
okini3939 0:629617d401de 185 }
okini3939 0:629617d401de 186
okini3939 0:629617d401de 187 // send ArtDmx Packet
okini3939 0:629617d401de 188 int DmxArtNet::Send_ArtDmx(int univ, int physical, char *data, int length) {
okini3939 0:629617d401de 189 Host Remote;
okini3939 0:629617d401de 190
okini3939 0:629617d401de 191 // build a artdmx packet
okini3939 0:629617d401de 192 memcpy(ArtDMX.Data, data, length);
okini3939 0:629617d401de 193 ArtDMX.Universes = univ;
okini3939 0:629617d401de 194 ArtDMX.Length = htons(length);
okini3939 0:629617d401de 195 ArtDMX.Physical = physical;
okini3939 0:629617d401de 196 ArtDMX.Sequence ++;
okini3939 0:629617d401de 197
okini3939 0:629617d401de 198 // set place to send
okini3939 0:629617d401de 199 Remote = Host(BCastAddress, ArtUDPPort, NULL);
okini3939 0:629617d401de 200
okini3939 0:629617d401de 201 // send it off
okini3939 0:629617d401de 202 _art.sendto((char*)&ArtDMX, sizeof(ArtDMX), &Remote);
okini3939 0:629617d401de 203
okini3939 0:629617d401de 204 return 0;
okini3939 0:629617d401de 205 }
okini3939 0:629617d401de 206
okini3939 0:629617d401de 207
okini3939 0:629617d401de 208
okini3939 0:629617d401de 209 void DmxArtNet::InitArtPollReplyDefaults () {
okini3939 0:629617d401de 210 memcpy(ArtPollReply.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 211 ArtPollReply.OpCode = OP_PollReply; // reply packet
okini3939 0:629617d401de 212 ArtPollReply.Version = ArtVersion;
okini3939 0:629617d401de 213
okini3939 0:629617d401de 214 memcpy(&ArtPollReply.Addr, &localaddr, sizeof(localaddr));
okini3939 0:629617d401de 215 strncpy(ArtPollReply.ShortName, STR_ShortName, 18);
okini3939 0:629617d401de 216 strncpy(ArtPollReply.LongName, STR_LongName, 64);
okini3939 0:629617d401de 217 strncpy(ArtPollReply.NodeReport, "OK", 64);
okini3939 0:629617d401de 218 ArtPollReply.Style = StyleNode;
okini3939 0:629617d401de 219
okini3939 0:629617d401de 220 mbed_mac_address((char*)&ArtPollReply.Mac);
okini3939 0:629617d401de 221
okini3939 0:629617d401de 222 ArtPollReply.NumPortsH = 0;
okini3939 0:629617d401de 223 ArtPollReply.NumPorts = 0;
okini3939 0:629617d401de 224 ArtPollReply.Swout[0] = 0;
okini3939 0:629617d401de 225 ArtPollReply.Swout[1] = 0;
okini3939 0:629617d401de 226 ArtPollReply.Swout[2] = 0;
okini3939 0:629617d401de 227 ArtPollReply.Swout[3] = 0;
okini3939 0:629617d401de 228 ArtPollReply.Swin[0] = 0;
okini3939 0:629617d401de 229 ArtPollReply.Swin[1] = 0;
okini3939 0:629617d401de 230 ArtPollReply.Swin[2] = 0;
okini3939 0:629617d401de 231 ArtPollReply.Swin[3] = 0;
okini3939 0:629617d401de 232
okini3939 0:629617d401de 233 ArtPollReply.GoodOutput[0] = 0;
okini3939 0:629617d401de 234 ArtPollReply.GoodOutput[1] = 0;
okini3939 0:629617d401de 235 ArtPollReply.GoodOutput[2] = 0;
okini3939 0:629617d401de 236 ArtPollReply.GoodOutput[3] = 0;
okini3939 0:629617d401de 237 ArtPollReply.PortType[0] = 255;
okini3939 0:629617d401de 238 ArtPollReply.PortType[1] = 255;
okini3939 0:629617d401de 239 ArtPollReply.PortType[2] = 255;
okini3939 0:629617d401de 240 ArtPollReply.PortType[3] = 255;
okini3939 0:629617d401de 241 }
okini3939 0:629617d401de 242
okini3939 0:629617d401de 243 // send ArtPoll Reply
okini3939 0:629617d401de 244 int DmxArtNet::SendArtPollReply () {
okini3939 0:629617d401de 245
okini3939 0:629617d401de 246 // send the packet
okini3939 0:629617d401de 247 _art.sendto((char*)&ArtPollReply, sizeof(ArtPollReply), &RemoteSin);
okini3939 0:629617d401de 248
okini3939 0:629617d401de 249 return 0;
okini3939 0:629617d401de 250 }