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

Dependents:   ArtNode ArtNode DMXStation ArtNodeLED ... more

Committer:
okini3939
Date:
Fri Sep 13 06:16:58 2019 +0000
Revision:
2:0753f1ed1dec
Parent:
1:c59dc374fc64
Child:
3:89aa639c946a
fix multi universe

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 2:0753f1ed1dec 10 * for mbed ported by Suga 2011, 2017
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 2:0753f1ed1dec 17 #include "EthernetInterface.h"
okini3939 0:629617d401de 18 #include "DmxArtNet.h"
okini3939 0:629617d401de 19 #include <stdio.h>
okini3939 0:629617d401de 20 #include <string.h>
okini3939 0:629617d401de 21
okini3939 2:0753f1ed1dec 22 //#define DEBUG
okini3939 2:0753f1ed1dec 23 #ifdef DEBUG
okini3939 2:0753f1ed1dec 24 #define DBG(...) printf("" __VA_ARGS__)
okini3939 2:0753f1ed1dec 25 #else
okini3939 2:0753f1ed1dec 26 #define DBG(...)
okini3939 2:0753f1ed1dec 27 #endif
okini3939 2:0753f1ed1dec 28
okini3939 2:0753f1ed1dec 29 /*
okini3939 0:629617d401de 30 // host to network short
okini3939 0:629617d401de 31 #define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) )
okini3939 0:629617d401de 32 #define ntohs( x ) htons(x)
okini3939 0:629617d401de 33 // host to network long
okini3939 0:629617d401de 34 #define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \
okini3939 0:629617d401de 35 | (( (x) << 8 ) & 0x00FF0000) \
okini3939 0:629617d401de 36 | (( (x) >> 8 ) & 0x0000FF00) \
okini3939 0:629617d401de 37 | (( (x) >> 24 ) & 0x000000FF) )
okini3939 0:629617d401de 38 #define ntohl( x ) htonl(x)
okini3939 2:0753f1ed1dec 39 */
okini3939 0:629617d401de 40
okini3939 0:629617d401de 41 extern "C" void mbed_mac_address(char *s);
okini3939 0:629617d401de 42
okini3939 0:629617d401de 43
okini3939 2:0753f1ed1dec 44 DmxArtNet::DmxArtNet () {
okini3939 2:0753f1ed1dec 45 BindIpAddress[0] = 0;
okini3939 2:0753f1ed1dec 46 BCastAddress[0] = 0;
okini3939 2:0753f1ed1dec 47 Init_ArtDMX();
okini3939 2:0753f1ed1dec 48 InitArtPollReplyDefaults();
okini3939 2:0753f1ed1dec 49 }
okini3939 2:0753f1ed1dec 50
okini3939 0:629617d401de 51 // function to make a word (16bit) from two bytes (2 x 8bit)
okini3939 0:629617d401de 52 int DmxArtNet::makeword16 (int lsb, int msb) {
okini3939 0:629617d401de 53 return (msb << 8) + lsb;
okini3939 0:629617d401de 54 }
okini3939 0:629617d401de 55
okini3939 0:629617d401de 56 // report a socket error, halt program
okini3939 0:629617d401de 57 void DmxArtNet::SocketErrorOccured (char *proc) {
okini3939 0:629617d401de 58 LError = 1;
okini3939 0:629617d401de 59 snprintf(LErrorString, sizeof(LErrorString), "socket> error occured in '%s'\r\n", proc);
okini3939 0:629617d401de 60 DBG("%s", LErrorString);
okini3939 0:629617d401de 61 }
okini3939 0:629617d401de 62
okini3939 0:629617d401de 63 // clear error
okini3939 0:629617d401de 64 void DmxArtNet::ClearError () {
okini3939 0:629617d401de 65 LError = 0;
okini3939 0:629617d401de 66 }
okini3939 0:629617d401de 67
okini3939 0:629617d401de 68 int DmxArtNet::Init () {
okini3939 0:629617d401de 69 int i;
okini3939 2:0753f1ed1dec 70 int err;
okini3939 0:629617d401de 71
okini3939 2:0753f1ed1dec 72 rxlen = 0;
okini3939 2:0753f1ed1dec 73 cb_ArtParser = NULL;
okini3939 0:629617d401de 74 LError = 0; // no error yet :)
okini3939 2:0753f1ed1dec 75 LastRecievedUniverse = 0;
okini3939 2:0753f1ed1dec 76
okini3939 2:0753f1ed1dec 77 // Init_ArtDMX(); // initialize ArtDmx structure
okini3939 0:629617d401de 78
okini3939 2:0753f1ed1dec 79 if (BindIpAddress[0] == 0) {
okini3939 2:0753f1ed1dec 80 char mac[6];
okini3939 2:0753f1ed1dec 81 mbed_mac_address(mac);
okini3939 2:0753f1ed1dec 82 sprintf(BindIpAddress, "%d.%d.%d.%d", 2, mac[3], mac[4], mac[5]);
okini3939 2:0753f1ed1dec 83 strcpy(SubNetMask, "255.0.0.0");
okini3939 0:629617d401de 84 }
okini3939 2:0753f1ed1dec 85 if (BCastAddress[0] == 0) {
okini3939 2:0753f1ed1dec 86 bcast(BCastAddress, BindIpAddress, SubNetMask);
okini3939 2:0753f1ed1dec 87 }
okini3939 2:0753f1ed1dec 88 RemoteSin.set_address(BCastAddress, ArtUDPPort);
okini3939 2:0753f1ed1dec 89
okini3939 2:0753f1ed1dec 90 err = _art.bind(ArtUDPPort);
okini3939 0:629617d401de 91 if (err) {
okini3939 0:629617d401de 92 SocketErrorOccured("Bind error");
okini3939 0:629617d401de 93 return -1;
okini3939 0:629617d401de 94 }
okini3939 2:0753f1ed1dec 95 // _art.set_broadcasting(true);
okini3939 0:629617d401de 96
okini3939 2:0753f1ed1dec 97 int ip[4];
okini3939 2:0753f1ed1dec 98 sscanf(BindIpAddress, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]);
okini3939 2:0753f1ed1dec 99 for (i = 0; i < 4; i ++) {
okini3939 2:0753f1ed1dec 100 localaddr.IP[i] = ip[i];
okini3939 2:0753f1ed1dec 101 }
okini3939 2:0753f1ed1dec 102 localaddr.Port = ArtUDPPort;
okini3939 2:0753f1ed1dec 103 ArtPollReply.Addr = localaddr;
okini3939 0:629617d401de 104
okini3939 2:0753f1ed1dec 105 for (i = 0; i < ArtMaxUniv; i ++) {
okini3939 2:0753f1ed1dec 106 // DmxIn[i] = new unsigned char[DMX_SIZE];
okini3939 2:0753f1ed1dec 107 DmxIn[i] = (unsigned char*)malloc(DMX_SIZE);
okini3939 2:0753f1ed1dec 108 memset(DmxIn[i], 0, DMX_SIZE);
okini3939 2:0753f1ed1dec 109 }
okini3939 2:0753f1ed1dec 110
okini3939 2:0753f1ed1dec 111 thread = new Thread(&DmxArtNet::task_UDPSocket, (void*)this, osPriorityNormal, 1024*4);
okini3939 0:629617d401de 112
okini3939 0:629617d401de 113 return 0;
okini3939 0:629617d401de 114 }
okini3939 0:629617d401de 115
okini3939 2:0753f1ed1dec 116 void DmxArtNet::task_UDPSocket (void const *arg) {
okini3939 2:0753f1ed1dec 117 DmxArtNet *inst = (DmxArtNet*)arg;
okini3939 2:0753f1ed1dec 118
okini3939 2:0753f1ed1dec 119 inst->on_UDPSocketEvent();
okini3939 2:0753f1ed1dec 120 }
okini3939 2:0753f1ed1dec 121
okini3939 2:0753f1ed1dec 122 void DmxArtNet::on_UDPSocketEvent () {
okini3939 2:0753f1ed1dec 123 int n;
okini3939 2:0753f1ed1dec 124
okini3939 2:0753f1ed1dec 125 for (;;) {
okini3939 2:0753f1ed1dec 126 Work();
okini3939 2:0753f1ed1dec 127
okini3939 2:0753f1ed1dec 128 n = _art.receiveFrom(RemoteSin, (char*)buf, sizeof(buf));
okini3939 2:0753f1ed1dec 129 if (n < 0) break;
okini3939 2:0753f1ed1dec 130 if (n == 0) continue;
okini3939 2:0753f1ed1dec 131 rxlen = n;
okini3939 0:629617d401de 132 }
okini3939 0:629617d401de 133 }
okini3939 0:629617d401de 134
okini3939 0:629617d401de 135 int DmxArtNet::Work() {
okini3939 2:0753f1ed1dec 136 int i, n;
okini3939 2:0753f1ed1dec 137 struct ArtPacketHeader *ArtHead = (ArtPacketHeader*)buf;
okini3939 0:629617d401de 138
okini3939 0:629617d401de 139 if (rxlen >= sizeof(ArtPacketHeader)) {
okini3939 0:629617d401de 140 // retreive the packet header
okini3939 0:629617d401de 141
okini3939 0:629617d401de 142 // if looback disabled
okini3939 2:0753f1ed1dec 143 if (strcmp(RemoteSin.get_address(), BindIpAddress) == NULL) {
okini3939 0:629617d401de 144 DBG("ArtNet> loopback detected\r\n");
okini3939 0:629617d401de 145
okini3939 0:629617d401de 146 rxlen = 0;
okini3939 0:629617d401de 147 return 0; // don't read packets
okini3939 0:629617d401de 148 // which we sent!
okini3939 0:629617d401de 149 }
okini3939 0:629617d401de 150
okini3939 2:0753f1ed1dec 151 // confirm is vaild art-net packet
okini3939 2:0753f1ed1dec 152 if (strncmp(ArtHead->ID, ArtHeaderID, 8) != 0) {
okini3939 2:0753f1ed1dec 153 rxlen = 0;
okini3939 2:0753f1ed1dec 154 return 0;
okini3939 2:0753f1ed1dec 155 }
okini3939 2:0753f1ed1dec 156
okini3939 2:0753f1ed1dec 157 DBG("ArtNet> RX: %d OpCode: %04x\r\n", rxlen, ArtHead->OpCode);
okini3939 0:629617d401de 158
okini3939 2:0753f1ed1dec 159 switch (ArtHead->OpCode) { // determine packet type
okini3939 0:629617d401de 160
okini3939 2:0753f1ed1dec 161 case OP_Output: // 0x5000 An ArtDMX Packet, containts dmx universe
okini3939 2:0753f1ed1dec 162 if (rxlen >= sizeof(struct ArtDMX_Packet) - (DMX_SIZE - 2)) {
okini3939 2:0753f1ed1dec 163 struct ArtDMX_Packet *artdmx = (struct ArtDMX_Packet*)buf;
okini3939 2:0753f1ed1dec 164
okini3939 2:0753f1ed1dec 165 // check data length
okini3939 2:0753f1ed1dec 166 if (ntohs(artdmx->Length) > DMX_SIZE || (artdmx->Universes & 0x7ff0) != (NetSwitch & 0x7ff0)) {
okini3939 2:0753f1ed1dec 167 break;
okini3939 2:0753f1ed1dec 168 }
okini3939 0:629617d401de 169
okini3939 2:0753f1ed1dec 170 for (i = 0; i < ArtMaxUniv; i ++) {
okini3939 2:0753f1ed1dec 171 if ( (ArtMaxUniv <= 4 && ArtPollReply.Swout[i] == (artdmx->Universes & 0x0f)) ||
okini3939 2:0753f1ed1dec 172 (ArtMaxUniv > 4 && ArtPorts.Swout[i] == (artdmx->Universes & 0x0f)) ) {
okini3939 2:0753f1ed1dec 173 LastRecievedUniverse |= (1<<i);
okini3939 2:0753f1ed1dec 174 // get the dmx data
okini3939 2:0753f1ed1dec 175 memcpy(DmxIn[i], artdmx->Data, ntohs(artdmx->Length));
okini3939 2:0753f1ed1dec 176 DBG(" <Art-Dmx> Univ: %d Length: %d Ch1: %d\r\n", artdmx->Universes, ntohs(artdmx->Length), DmxIn[i][0]);
okini3939 2:0753f1ed1dec 177 DBG(" from %s\r\n", RemoteSin.get_address());
okini3939 2:0753f1ed1dec 178 rxlen = 0;
okini3939 2:0753f1ed1dec 179 return 1; // something happened!
okini3939 2:0753f1ed1dec 180 }
okini3939 2:0753f1ed1dec 181 }
okini3939 2:0753f1ed1dec 182 }
okini3939 2:0753f1ed1dec 183 break; // OP_Output
okini3939 2:0753f1ed1dec 184
okini3939 2:0753f1ed1dec 185 case OP_Poll: // 0x2000
okini3939 2:0753f1ed1dec 186 if (rxlen == sizeof(struct ArtPoll_Packet)) {
okini3939 2:0753f1ed1dec 187 struct ArtPoll_Packet *artpoll = (struct ArtPoll_Packet*)buf;
okini3939 0:629617d401de 188
okini3939 2:0753f1ed1dec 189 if (!(artpoll->TalkToMe & 1)) {
okini3939 2:0753f1ed1dec 190 RemoteSin.set_address(BCastAddress, ArtUDPPort);
okini3939 2:0753f1ed1dec 191 }
okini3939 2:0753f1ed1dec 192 DBG(" <Art-Poll> Ver: %d TalkToMe: %d\r\n", ArtPoll.Version, ArtPoll.TalkToMe);
okini3939 2:0753f1ed1dec 193 SendArtPollReply(); // send a reply to the ArtPoll
okini3939 2:0753f1ed1dec 194 }
okini3939 2:0753f1ed1dec 195 break; // OP_Poll
okini3939 0:629617d401de 196
okini3939 2:0753f1ed1dec 197 case OP_PollReply: // 0x2100
okini3939 2:0753f1ed1dec 198 {
okini3939 2:0753f1ed1dec 199 struct ArtPollReply_Packet *pollreply = (struct ArtPollReply_Packet*)buf;
okini3939 2:0753f1ed1dec 200
okini3939 2:0753f1ed1dec 201 DBG(" <Art-PollReply> Startus: %02x Name: %s\r\n", pollreply->Status, pollreply->ShortName);
okini3939 2:0753f1ed1dec 202 }
okini3939 2:0753f1ed1dec 203 break; // OP_PollReply
okini3939 2:0753f1ed1dec 204
okini3939 2:0753f1ed1dec 205 case OP_Address: // 0x6000
okini3939 2:0753f1ed1dec 206 if (rxlen == sizeof(struct ArtAddress_Packet)) {
okini3939 2:0753f1ed1dec 207 struct ArtAddress_Packet *address = (struct ArtAddress_Packet *)buf;
okini3939 0:629617d401de 208
okini3939 2:0753f1ed1dec 209 if ((address->NetSwitch & 0x80) && (address->SubSwitch & 0x80)) {
okini3939 2:0753f1ed1dec 210 NetSwitch = ((address->NetSwitch & 0x7f) << 8) | ((address->SubSwitch & 0x0f) << 4);
okini3939 2:0753f1ed1dec 211 ArtPollReply.NetSwitch = (NetSwitch >> 8) & 0x7f;
okini3939 2:0753f1ed1dec 212 ArtPollReply.SubSwitch = (NetSwitch >> 4) & 0x0f;
okini3939 2:0753f1ed1dec 213 }
okini3939 2:0753f1ed1dec 214 if (address->ShortName[0]) {
okini3939 2:0753f1ed1dec 215 strncpy(ArtPollReply.ShortName, address->ShortName, 18);
okini3939 2:0753f1ed1dec 216 }
okini3939 2:0753f1ed1dec 217 if (address->LongName[0]) {
okini3939 2:0753f1ed1dec 218 strncpy(ArtPollReply.LongName, address->LongName, 64);
okini3939 2:0753f1ed1dec 219 }
okini3939 2:0753f1ed1dec 220 if (address->BindIndex) {
okini3939 2:0753f1ed1dec 221 n = (address->BindIndex - 1) * 4;
okini3939 2:0753f1ed1dec 222 } else {
okini3939 2:0753f1ed1dec 223 n = 0;
okini3939 2:0753f1ed1dec 224 }
okini3939 2:0753f1ed1dec 225 for (i = 0; i < 4; i ++) {
okini3939 2:0753f1ed1dec 226 if (address->Swin[i] != 0x7f) {
okini3939 2:0753f1ed1dec 227 ArtPollReply.Swin[i] = address->Swin[i] & 0x0f;
okini3939 2:0753f1ed1dec 228 ArtPorts.Swin[n + i] = address->Swin[i] & 0x0f;
okini3939 2:0753f1ed1dec 229 if (address->Swin[i] & 0x80) {
okini3939 2:0753f1ed1dec 230 ArtPollReply.PortType[i] |= 0x40;
okini3939 2:0753f1ed1dec 231 ArtPorts.PortType[n + i] |= 0x40;
okini3939 2:0753f1ed1dec 232 } else {
okini3939 2:0753f1ed1dec 233 ArtPollReply.PortType[i] &= ~0x40;
okini3939 2:0753f1ed1dec 234 ArtPorts.PortType[n + i] &= ~0x40;
okini3939 2:0753f1ed1dec 235 }
okini3939 2:0753f1ed1dec 236 }
okini3939 2:0753f1ed1dec 237 if (address->Swout[i] != 0x7f) {
okini3939 2:0753f1ed1dec 238 ArtPollReply.Swout[i] = address->Swout[i] & 0x0f;
okini3939 2:0753f1ed1dec 239 ArtPorts.Swout[n + i] = address->Swout[i] & 0x0f;
okini3939 2:0753f1ed1dec 240 if (address->Swout[i] & 0x80) {
okini3939 2:0753f1ed1dec 241 ArtPollReply.PortType[i] |= 0x80;
okini3939 2:0753f1ed1dec 242 ArtPorts.PortType[n + i] |= 0x80;
okini3939 2:0753f1ed1dec 243 } else {
okini3939 2:0753f1ed1dec 244 ArtPollReply.PortType[i] &= ~0x80;
okini3939 2:0753f1ed1dec 245 ArtPorts.PortType[n + i] &= ~0x80;
okini3939 2:0753f1ed1dec 246 }
okini3939 2:0753f1ed1dec 247 }
okini3939 2:0753f1ed1dec 248 }
okini3939 2:0753f1ed1dec 249
okini3939 2:0753f1ed1dec 250 if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 251 SendArtPollReply(); // send a reply to the ArtPoll
okini3939 2:0753f1ed1dec 252 DBG(" <Art-Address> NetSwitch: %02x Command: %02x\r\n", NetSwitch, address->Command);
okini3939 2:0753f1ed1dec 253 }
okini3939 2:0753f1ed1dec 254 break;
okini3939 0:629617d401de 255
okini3939 2:0753f1ed1dec 256 case OP_IpProg: // 0xf800
okini3939 2:0753f1ed1dec 257 if (rxlen == sizeof(struct ArtIpProg_Packet)) {
okini3939 2:0753f1ed1dec 258 struct ArtIpProg_Packet *ipprog = (struct ArtIpProg_Packet *)buf;
okini3939 2:0753f1ed1dec 259
okini3939 2:0753f1ed1dec 260 if (ipprog->Command & (1<<7)) {
okini3939 2:0753f1ed1dec 261 if (ipprog->Command & (1<<6)) { // dhcp
okini3939 2:0753f1ed1dec 262 BindIpAddress[0] = 0;
okini3939 2:0753f1ed1dec 263 }
okini3939 2:0753f1ed1dec 264 if (ipprog->Command & (1<<2)) { // ip addrress
okini3939 2:0753f1ed1dec 265 sprintf(BindIpAddress, "%d.%d.%d.%d", ipprog->ProgIp[0], ipprog->ProgIp[1], ipprog->ProgIp[2], ipprog->ProgIp[3]);
okini3939 2:0753f1ed1dec 266 // sprintf(DGateWay, "%d.%d.%d.%d", ipprog->Padding[0], ipprog->Padding[1], ipprog->Padding[2], ipprog->Padding[3]);
okini3939 2:0753f1ed1dec 267 }
okini3939 2:0753f1ed1dec 268 if (ipprog->Command & (1<<1)) { // subnet mask
okini3939 2:0753f1ed1dec 269 sprintf(SubNetMask, "%d.%d.%d.%d", ipprog->ProgSm[0], ipprog->ProgSm[1], ipprog->ProgSm[2], ipprog->ProgSm[3]);
okini3939 2:0753f1ed1dec 270 }
okini3939 2:0753f1ed1dec 271 bcast(BCastAddress, BindIpAddress, SubNetMask);
okini3939 2:0753f1ed1dec 272 }
okini3939 2:0753f1ed1dec 273
okini3939 2:0753f1ed1dec 274 // if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 275 SendArtIpProgReply();
okini3939 2:0753f1ed1dec 276 DBG(" <Art-IpProg> NetSwitch: %02x Command: %02x\r\n", NetSwitch, ipprog->Command);
okini3939 2:0753f1ed1dec 277 }
okini3939 2:0753f1ed1dec 278 if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 279 break;
okini3939 0:629617d401de 280
okini3939 2:0753f1ed1dec 281 case OP_OpTodRequest: // 0x8000
okini3939 2:0753f1ed1dec 282 if (rxlen == sizeof(struct ArtTodRequest_Packet)) {
okini3939 2:0753f1ed1dec 283 struct ArtTodRequest_Packet *todreq = (struct ArtTodRequest_Packet *)buf;
okini3939 2:0753f1ed1dec 284 if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 285 for (i = 0; i < todreq->AddCount; i ++) {
okini3939 2:0753f1ed1dec 286 SendArtTodData(todreq->Address[i]);
okini3939 2:0753f1ed1dec 287 }
okini3939 2:0753f1ed1dec 288 }
okini3939 2:0753f1ed1dec 289 break;
okini3939 2:0753f1ed1dec 290
okini3939 2:0753f1ed1dec 291 case OP_OpTodControl: // 0x8200
okini3939 2:0753f1ed1dec 292 if (rxlen == sizeof(struct ArtTodControl_Packet)) {
okini3939 2:0753f1ed1dec 293 struct ArtTodControl_Packet *tod = (struct ArtTodControl_Packet *)buf;
okini3939 2:0753f1ed1dec 294 if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 295 if (tod->Command == 0x01) {
okini3939 2:0753f1ed1dec 296 SendArtTodData(tod->Address);
okini3939 2:0753f1ed1dec 297 }
okini3939 2:0753f1ed1dec 298 }
okini3939 2:0753f1ed1dec 299 break;
okini3939 2:0753f1ed1dec 300
okini3939 2:0753f1ed1dec 301 case OP_OpRdm: // 0x8300
okini3939 2:0753f1ed1dec 302 case OP_OpRdmSub: // 0x8400
okini3939 2:0753f1ed1dec 303 default:
okini3939 2:0753f1ed1dec 304 if (cb_ArtParser) cb_ArtParser(ArtHead, rxlen);
okini3939 2:0753f1ed1dec 305 DBG(" <Unknown> OpCode: %04x\r\n", ArtHead->OpCode);
okini3939 2:0753f1ed1dec 306 break;
okini3939 0:629617d401de 307 } // case packet type
okini3939 0:629617d401de 308 }
okini3939 0:629617d401de 309
okini3939 0:629617d401de 310 rxlen = 0;
okini3939 0:629617d401de 311 return 0;
okini3939 0:629617d401de 312 }
okini3939 0:629617d401de 313
okini3939 0:629617d401de 314 // socket shutdown
okini3939 0:629617d401de 315 void DmxArtNet::Done () {
okini3939 0:629617d401de 316 _art.close();
okini3939 0:629617d401de 317 }
okini3939 0:629617d401de 318
okini3939 0:629617d401de 319 // init ArtDMX packet
okini3939 0:629617d401de 320 void DmxArtNet::Init_ArtDMX () {
okini3939 0:629617d401de 321 // header stuff
okini3939 2:0753f1ed1dec 322 memset(&ArtDMX, 0, sizeof(ArtDMX));
okini3939 0:629617d401de 323 memcpy(ArtDMX.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 324 ArtDMX.OpCode = OP_Output;
okini3939 0:629617d401de 325 ArtDMX.Version = ArtVersion;
okini3939 0:629617d401de 326 // dmx stuff
okini3939 0:629617d401de 327 ArtDMX.Universes = 0; // this is the destination for the dmx
okini3939 0:629617d401de 328 ArtDMX.Sequence = 0;
okini3939 2:0753f1ed1dec 329 ArtDMX.Length = htons(DMX_SIZE);
okini3939 0:629617d401de 330 }
okini3939 0:629617d401de 331
okini3939 0:629617d401de 332 // send ArtDmx Packet
okini3939 0:629617d401de 333 int DmxArtNet::Send_ArtDmx(int univ, int physical, char *data, int length) {
okini3939 2:0753f1ed1dec 334 Endpoint Remote;
okini3939 0:629617d401de 335
okini3939 0:629617d401de 336 // build a artdmx packet
okini3939 0:629617d401de 337 memcpy(ArtDMX.Data, data, length);
okini3939 2:0753f1ed1dec 338 ArtDMX.Universes = (NetSwitch & 0x7ff0) | univ;
okini3939 0:629617d401de 339 ArtDMX.Length = htons(length);
okini3939 0:629617d401de 340 ArtDMX.Physical = physical;
okini3939 0:629617d401de 341 ArtDMX.Sequence ++;
okini3939 0:629617d401de 342
okini3939 0:629617d401de 343 // set place to send
okini3939 2:0753f1ed1dec 344 Remote.set_address(BCastAddress, ArtUDPPort);
okini3939 0:629617d401de 345
okini3939 0:629617d401de 346 // send it off
okini3939 2:0753f1ed1dec 347 _art.sendTo(Remote, (char*)&ArtDMX, sizeof(ArtDMX));
okini3939 0:629617d401de 348
okini3939 0:629617d401de 349 return 0;
okini3939 0:629617d401de 350 }
okini3939 0:629617d401de 351
okini3939 0:629617d401de 352
okini3939 0:629617d401de 353 void DmxArtNet::InitArtPollReplyDefaults () {
okini3939 2:0753f1ed1dec 354 memset(&ArtPollReply, 0, sizeof(ArtPollReply));
okini3939 2:0753f1ed1dec 355 memset(&ArtPorts, 0, sizeof(ArtPorts));
okini3939 0:629617d401de 356 memcpy(ArtPollReply.ID, ArtHeaderID, 8);
okini3939 0:629617d401de 357 ArtPollReply.OpCode = OP_PollReply; // reply packet
okini3939 0:629617d401de 358 ArtPollReply.Version = ArtVersion;
okini3939 0:629617d401de 359
okini3939 2:0753f1ed1dec 360 ArtPollReply.NetSwitch = (NetSwitch >> 8) & 0x7f;
okini3939 2:0753f1ed1dec 361 ArtPollReply.SubSwitch = (NetSwitch >> 4) & 0x0f;
okini3939 2:0753f1ed1dec 362 ArtPollReply.OEM = htons(OemId);
okini3939 2:0753f1ed1dec 363 ArtPollReply.Status = (3<<6)|(2<<4); // Normal mode, Universe programmed by network
okini3939 2:0753f1ed1dec 364
okini3939 2:0753f1ed1dec 365 ArtPollReply.Addr = localaddr;
okini3939 0:629617d401de 366 strncpy(ArtPollReply.ShortName, STR_ShortName, 18);
okini3939 0:629617d401de 367 strncpy(ArtPollReply.LongName, STR_LongName, 64);
okini3939 0:629617d401de 368 strncpy(ArtPollReply.NodeReport, "OK", 64);
okini3939 0:629617d401de 369 ArtPollReply.Style = StyleNode;
okini3939 0:629617d401de 370
okini3939 0:629617d401de 371 mbed_mac_address((char*)&ArtPollReply.Mac);
okini3939 0:629617d401de 372
okini3939 2:0753f1ed1dec 373 ArtPollReply.PortType[0] = 0;
okini3939 2:0753f1ed1dec 374 ArtPollReply.PortType[1] = 0;
okini3939 2:0753f1ed1dec 375 ArtPollReply.PortType[2] = 0;
okini3939 2:0753f1ed1dec 376 ArtPollReply.PortType[3] = 0;
okini3939 0:629617d401de 377 }
okini3939 0:629617d401de 378
okini3939 0:629617d401de 379 // send ArtPoll Reply
okini3939 0:629617d401de 380 int DmxArtNet::SendArtPollReply () {
okini3939 2:0753f1ed1dec 381 int i, j, n;
okini3939 0:629617d401de 382
okini3939 0:629617d401de 383 // send the packet
okini3939 2:0753f1ed1dec 384 // DBG("SendArtPollReply> %s:%d\r\n", RemoteSin.get_address(), RemoteSin.get_port());
okini3939 2:0753f1ed1dec 385 if (ArtMaxUniv <= 4) {
okini3939 2:0753f1ed1dec 386 _art.sendTo(RemoteSin, (char*)&ArtPollReply, sizeof(ArtPollReply));
okini3939 2:0753f1ed1dec 387 } else {
okini3939 2:0753f1ed1dec 388 for (i = 0; i < (ArtMaxUniv + 3) / 4; i ++) {
okini3939 2:0753f1ed1dec 389 n = i * 4;
okini3939 2:0753f1ed1dec 390 ArtPollReply.BindIndex = 1 + i;
okini3939 2:0753f1ed1dec 391 ArtPollReply.NumPorts = ArtMaxUniv - n < 4 ? ArtMaxUniv - n : 4;
okini3939 2:0753f1ed1dec 392 for (j = 0; j < ArtPollReply.NumPorts; j ++) {
okini3939 2:0753f1ed1dec 393 ArtPollReply.PortType[j] = ArtPorts.PortType[n + j];
okini3939 2:0753f1ed1dec 394 ArtPollReply.GoodInput[j] = ArtPorts.GoodInput[n + j];
okini3939 2:0753f1ed1dec 395 ArtPollReply.GoodOutput[j] = ArtPorts.GoodOutput[n + j];
okini3939 2:0753f1ed1dec 396 ArtPollReply.Swin[j] = ArtPorts.Swin[n + j];
okini3939 2:0753f1ed1dec 397 ArtPollReply.Swout[j] = ArtPorts.Swout[n + j];
okini3939 2:0753f1ed1dec 398 }
okini3939 2:0753f1ed1dec 399 for (; j < 4; j ++) {
okini3939 2:0753f1ed1dec 400 ArtPollReply.PortType[j] = 0;
okini3939 2:0753f1ed1dec 401 ArtPollReply.GoodInput[j] = 0;
okini3939 2:0753f1ed1dec 402 ArtPollReply.GoodOutput[j] = 0;
okini3939 2:0753f1ed1dec 403 ArtPollReply.Swin[j] = 0;
okini3939 2:0753f1ed1dec 404 ArtPollReply.Swout[j] = 0;
okini3939 2:0753f1ed1dec 405 }
okini3939 2:0753f1ed1dec 406 _art.sendTo(RemoteSin, (char*)&ArtPollReply, sizeof(ArtPollReply));
okini3939 2:0753f1ed1dec 407 }
okini3939 2:0753f1ed1dec 408 }
okini3939 2:0753f1ed1dec 409 return 0;
okini3939 2:0753f1ed1dec 410 }
okini3939 2:0753f1ed1dec 411
okini3939 2:0753f1ed1dec 412 // send ArtIpProg Reply
okini3939 2:0753f1ed1dec 413 int DmxArtNet::SendArtIpProgReply () {
okini3939 2:0753f1ed1dec 414 ArtIpProgReply_Packet ArtIpProgReply;
okini3939 2:0753f1ed1dec 415 int ip[4];
okini3939 2:0753f1ed1dec 416
okini3939 2:0753f1ed1dec 417 memset(&ArtIpProgReply, 0, sizeof(ArtIpProgReply));
okini3939 2:0753f1ed1dec 418 memcpy(ArtIpProgReply.ID, ArtHeaderID, 8);
okini3939 2:0753f1ed1dec 419 ArtIpProgReply.OpCode = OP_IpProgReply;
okini3939 2:0753f1ed1dec 420 ArtIpProgReply.Version = ArtVersion;
okini3939 2:0753f1ed1dec 421
okini3939 2:0753f1ed1dec 422 sscanf(BindIpAddress, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]);
okini3939 2:0753f1ed1dec 423 ArtIpProgReply.ProgIp[0] = ip[0];
okini3939 2:0753f1ed1dec 424 ArtIpProgReply.ProgIp[1] = ip[1];
okini3939 2:0753f1ed1dec 425 ArtIpProgReply.ProgIp[2] = ip[2];
okini3939 2:0753f1ed1dec 426 ArtIpProgReply.ProgIp[3] = ip[3];
okini3939 2:0753f1ed1dec 427 sscanf(SubNetMask, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]);
okini3939 2:0753f1ed1dec 428 ArtIpProgReply.ProgSm[0] = ip[0];
okini3939 2:0753f1ed1dec 429 ArtIpProgReply.ProgSm[1] = ip[1];
okini3939 2:0753f1ed1dec 430 ArtIpProgReply.ProgSm[2] = ip[2];
okini3939 2:0753f1ed1dec 431 ArtIpProgReply.ProgSm[3] = ip[3];
okini3939 2:0753f1ed1dec 432 ArtIpProgReply.ProgPortH = ArtUDPPort >> 8;
okini3939 2:0753f1ed1dec 433 ArtIpProgReply.ProgPort = ArtUDPPort & 0xff;
okini3939 2:0753f1ed1dec 434
okini3939 2:0753f1ed1dec 435 if (BindIpAddress[0] == '0') {
okini3939 2:0753f1ed1dec 436 ArtIpProgReply.Status = 0x40; // dhcp
okini3939 2:0753f1ed1dec 437 }
okini3939 2:0753f1ed1dec 438
okini3939 2:0753f1ed1dec 439 _art.sendTo(RemoteSin, (char*)&ArtIpProgReply, sizeof(ArtIpProgReply));
okini3939 0:629617d401de 440
okini3939 0:629617d401de 441 return 0;
okini3939 0:629617d401de 442 }
okini3939 2:0753f1ed1dec 443
okini3939 2:0753f1ed1dec 444 // send SendArtTod
okini3939 2:0753f1ed1dec 445 int DmxArtNet::SendArtTodData (int n) {
okini3939 2:0753f1ed1dec 446 ArtTodData_Packet ArtTodData;
okini3939 2:0753f1ed1dec 447
okini3939 2:0753f1ed1dec 448 memset(&ArtTodData, 0, sizeof(ArtTodData));
okini3939 2:0753f1ed1dec 449 memcpy(ArtTodData.ID, ArtHeaderID, 8);
okini3939 2:0753f1ed1dec 450 ArtTodData.OpCode = OP_OpTodData;
okini3939 2:0753f1ed1dec 451 ArtTodData.Version = ArtVersion;
okini3939 2:0753f1ed1dec 452
okini3939 2:0753f1ed1dec 453 ArtTodData.RdmVersion = 1;
okini3939 2:0753f1ed1dec 454 ArtTodData.Port = n + 1;
okini3939 2:0753f1ed1dec 455
okini3939 2:0753f1ed1dec 456 ArtTodData.UidTotalH = 0;
okini3939 2:0753f1ed1dec 457 ArtTodData.UidTotalL = 1;
okini3939 2:0753f1ed1dec 458 ArtTodData.BlockCount = 0;
okini3939 2:0753f1ed1dec 459 ArtTodData.UidCount = 2;
okini3939 2:0753f1ed1dec 460 ArtTodData.ToD[0] = 0x11;
okini3939 2:0753f1ed1dec 461 ArtTodData.ToD[1] = 0x22;
okini3939 2:0753f1ed1dec 462
okini3939 2:0753f1ed1dec 463 _art.sendTo(RemoteSin, (char*)&ArtTodData, sizeof(ArtTodData));
okini3939 2:0753f1ed1dec 464
okini3939 2:0753f1ed1dec 465 return 0;
okini3939 2:0753f1ed1dec 466 }
okini3939 2:0753f1ed1dec 467
okini3939 2:0753f1ed1dec 468 void DmxArtNet::bcast(char *dest, char *ipaddr, char *netmask) {
okini3939 2:0753f1ed1dec 469 unsigned char ip[4];
okini3939 2:0753f1ed1dec 470 int a[4], n[4];
okini3939 2:0753f1ed1dec 471
okini3939 2:0753f1ed1dec 472 sscanf(ipaddr, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
okini3939 2:0753f1ed1dec 473 sscanf(netmask, "%d.%d.%d.%d", &n[0], &n[1], &n[2], &n[3]);
okini3939 2:0753f1ed1dec 474 ip[0] = (a[0] & n[0]) | ~n[0];
okini3939 2:0753f1ed1dec 475 ip[1] = (a[1] & n[1]) | ~n[1];
okini3939 2:0753f1ed1dec 476 ip[2] = (a[2] & n[2]) | ~n[2];
okini3939 2:0753f1ed1dec 477 ip[3] = (a[3] & n[3]) | ~n[3];
okini3939 2:0753f1ed1dec 478 sprintf(dest, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
okini3939 2:0753f1ed1dec 479 }
okini3939 2:0753f1ed1dec 480
okini3939 2:0753f1ed1dec 481 void DmxArtNet::attach (void (*handler)(struct ArtPacketHeader *, int)) {
okini3939 2:0753f1ed1dec 482 cb_ArtParser = handler;
okini3939 2:0753f1ed1dec 483 }