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

Dependents:   ArtNode ArtNode DMXStation ArtNodeLED ... more

Committer:
okini3939
Date:
Fri Sep 13 08:03:40 2019 +0000
Revision:
3:89aa639c946a
Parent:
2:0753f1ed1dec
bug fix;

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