http://mbed.org/users/okini3939/notebook/art-net/
Dependents: ArtNode ArtNode DMXStation ArtNodeLED ... more
DmxArtNet.cpp@3:89aa639c946a, 2019-09-13 (annotated)
- 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?
User | Revision | Line number | New 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 | } |