jasonpodmore

Main Sketch

May 1st, 2014
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.55 KB | None | 0 0
  1. /***************************************************************************
  2. *
  3. * Title : Arduino based Art-Net -> LED Pixel, Digital LED Strip gateway
  4. * Version : v 0.2 beta
  5. * Last updated : 17.12.2012
  6. * Target : Arduino mega 2560, Arduino mega 1280, Arduino UNO *** Arduino IDE v0023 ***
  7. * Pixel number : Arduino mega 340 pixels (2 universes), Arduino UNO 170 pixels (1 universe)
  8. * Driver support : TM1803, TM1804, TM1809, TM1812, WS2811
  9. * Author : Toni Merino - merino.toni at gmail.com
  10. * Web : www.deskontrol.net/blog
  11. *
  12. * Based on code from Christoph Guillermet, http://www.le-chat-noir-numerique.fr - [email protected]
  13. *
  14. * Structures and definitions (common.h and packet.h) from libartnet (c)Simon Newton and Lutz Hillebrand (ilLUTZminator), www.opendmx.net
  15. *
  16. * Art-Net™ Designed by and Copyright Artistic Licence Holdings Ltd.
  17. *
  18. ***************************************************************************
  19. This program is free software; you can redistribute it and/or
  20. modify it under the terms of the GNU General Public License
  21. as published by the Free Software Foundation; either version 2 of
  22. the License, or (at your option) any later version.
  23.  
  24. This program is distributed in the hope that it will be useful,
  25. but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  27. General Public License for more details.
  28.  
  29. If you have no copy of the GNU General Public License, write to the
  30. Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  
  32. For other license models, please contact the author.
  33.  
  34. ;***************************************************************************/
  35. #include <SPI.h> // needed for Arduino versions later than 0018
  36. #include <Ethernet.h>
  37. #include <Udp.h> // UDP library from: [email protected] 12/30/2008
  38. #include <FastSPI_LED.h>
  39. #include "artnet_node.h"
  40. #include "common.h" // headers from libartnet
  41. #include "packets.h" // headers from libartnet, striped version
  42.  
  43. #define USE_UNIVERSE_0
  44. #define USE_UNIVERSE_1
  45.  
  46. uint8_t factory_mac [6] = { 1, 2, 3, 0, 0, 20}; // the mac address of node
  47. uint8_t factory_localIp [4] = { 2, 0, 0, 20}; // the IP address of node
  48. uint8_t factory_broadcastIp [4] = { 2, 255, 255, 255}; // broadcast IP address
  49. uint8_t factory_gateway [4] = { 2, 0, 0, 0}; // gateway IP address (use ip address of controller)
  50. uint8_t factory_subnetMask [4] = { 255, 0, 0, 0}; // network mask (art-net use 'A' network type)
  51.  
  52. uint8_t factory_swin [4] = { 0, 1, 2, 3};
  53. uint8_t factory_swout [4] = { 0, 1, 2, 3};
  54.  
  55. uint8_t factory_shortname [ARTNET_SHORT_NAME_LENGTH];
  56. uint8_t factory_longname [ARTNET_LONG_NAME_LENGTH];
  57.  
  58. uint16_t size1, size2;
  59.  
  60. // if you have more than 1 node and need to change addresses, change here node->sub = x
  61. // default value 0 you have output universes addressed as 0x00, 0x01, 0x02, 0x03
  62. // change value to 1 and you have output universes addressed as 0x10, 0x11, 0x12, 0x13
  63. // is a good idea implement a switch for change subnet address.
  64. uint8_t factory_subnet = 0;
  65.  
  66. artnet_node_t ArtNode;
  67. artnet_reply_t ArtPollReply;
  68. //artnet_ipprog_reply_t ArtIpprogReply; // not implemented yet
  69. artnet_packet_type_t packet_type;
  70.  
  71. #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  72. const int MAX_BUFFER_UDP = 1650;
  73. #define NUM_LEDS 340
  74. #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
  75. const int MAX_BUFFER_UDP = 550;
  76. #define NUM_LEDS 170
  77. #endif
  78.  
  79. volatile uint8_t packetBuffer [MAX_BUFFER_UDP]; //buffer to store incoming data
  80.  
  81. struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
  82. struct CRGB *leds;
  83.  
  84. #define PIN 4 // Arduino output pin to data input on pixels or digital led strips
  85.  
  86. void setup()
  87. {
  88. sprintf((char *)factory_shortname, "Pixel Node\0");
  89. sprintf((char *)factory_longname, "LED Pixel Node v1.0 (c)2012 Toni Merino www.deskontrol.net\0");
  90.  
  91. fill_art_node (&ArtNode);
  92.  
  93. #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  94. ArtNode.numbports = 2; // number of universes
  95. #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
  96. ArtNode.numbports = 1;
  97. #endif
  98.  
  99. fill_art_poll_reply (&ArtPollReply, &ArtNode);
  100. //fill_art_ipprog_reply (&ArtIpprogReply, &ArtNode);
  101.  
  102. // subnet mask needed because art-net uses 'A' type network (255.0.0.0), ethernet library defaults to 255.255.255.0
  103. Ethernet.begin(ArtNode.mac, ArtNode.localIp, ArtNode.gateway, ArtNode.subnetMask);
  104. Udp.begin(ArtNode.localPort);
  105.  
  106. FastSPI_LED.setLeds(NUM_LEDS);
  107. FastSPI_LED.setChipset(CFastSPI_LED::SPI_TM1809); //don't change.
  108.  
  109. FastSPI_LED.setPin(PIN);
  110.  
  111. FastSPI_LED.init();
  112. FastSPI_LED.start();
  113.  
  114. leds = (struct CRGB*)FastSPI_LED.getRGBData();
  115. }
  116.  
  117. void loop()
  118. {
  119. if( Udp.available() > ARNET_HEADER_SIZE )
  120. handle_packet();
  121. }
  122.  
  123. void handle_packet()
  124. {
  125. Udp.readPacket((uint8_t *)&packetBuffer, MAX_BUFFER_UDP, (uint8_t *)&ArtNode.remoteIp, (uint16_t *)&ArtNode.remotePort);
  126.  
  127. packet_type = (artnet_packet_type_t) get_packet_type((uint8_t *)&packetBuffer);
  128.  
  129. if(packet_type == 0) // bad packet
  130. {
  131. return;
  132. }
  133. if(packet_type == ARTNET_DMX)
  134. {
  135. handle_dmx((artnet_dmx_t *)&packetBuffer);
  136. }
  137. else if(packet_type == ARTNET_POLL)
  138. {
  139. if(sizeof(packetBuffer) < sizeof(artnet_poll_t))
  140. return;
  141. else
  142. handle_poll((artnet_poll_t *)&packetBuffer);
  143. } /*
  144. else if(packet_type == ARTNET_IPPROG)
  145. {
  146. if(sizeof(packetBuffer) < sizeof(artnet_ipprog_t))
  147. return;
  148. else
  149. handle_ipprog((artnet_ipprog_t *)&packetBuffer);
  150. } */
  151. else if(packet_type == ARTNET_ADDRESS)
  152. {
  153. if(sizeof(packetBuffer) < sizeof(artnet_address_t))
  154. return;
  155. else
  156. handle_address((artnet_address_t *)&packetBuffer);
  157. }
  158. }
  159.  
  160. uint16_t get_packet_type(uint8_t *packet) //this get artnet packet type
  161. {
  162. if (! memcmp( packet, ArtNode.id, 8))
  163. {
  164. return bytes_to_short(packet[9], packet[8]);
  165. }
  166. return 0;
  167. }
  168.  
  169. int handle_dmx(artnet_dmx_t *packet)
  170. {
  171. uint16_t packet_length = bytes_to_short(packet->lengthHi, packet->length);
  172.  
  173. if(packet->universe == 0)
  174. {
  175. size1 = packet_length;
  176. memcpy((uint8_t *)leds, packet->data, packet_length);
  177. }
  178. else if(packet->universe == 1)
  179. {
  180. size2 = packet_length;
  181. memcpy((uint8_t *)&leds[size1/3], packet->data, packet_length);
  182. }
  183.  
  184. FastSPI_LED.show();
  185. }
  186.  
  187. int handle_poll(artnet_poll_t *packet)
  188. {
  189. if((packet->ttm & 1) == 1) // controller say: send unicast reply
  190. {
  191. send_reply(UNICAST, (uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
  192. }
  193. else // controller say: send broadcast reply
  194. {
  195. send_reply(BROADCAST, (uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
  196. }
  197. }
  198. /*
  199. int handle_ipprog(artnet_ipprog_t *packet)
  200. {
  201. send_reply(UNICAST, (uint8_t *)&ArtIpprogReply, sizeof(ArtIpprogReply));//ojo
  202. }
  203. */
  204. int handle_address(artnet_address_t *packet) //not implemented yet
  205. {
  206. if(packet->subnet == 0)
  207. {
  208. memcpy (ArtNode.shortname, factory_shortname, sizeof(factory_shortname));
  209. memcpy (ArtNode.longname, factory_longname, sizeof(factory_longname));
  210. }
  211. else
  212. {
  213. memcpy (ArtNode.shortname, packet->shortname, ARTNET_SHORT_NAME_LENGTH);
  214. memcpy (ArtNode.longname, packet->longname, ARTNET_LONG_NAME_LENGTH);
  215. }
  216.  
  217. for(uint8_t i = 0; i <= 4; i++)
  218. {
  219. if(packet->swout[i] & 0x80)
  220. ArtNode.swout[i] = packet->swout[i] - 0x80;
  221. else if(packet->swout[0] == 0)
  222. ArtNode.swout[i] = factory_swout[i];
  223.  
  224. if(packet->swin[i] & 0x80)
  225. ArtNode.swin[i] = packet->swin[i] - 0x80;
  226. else if(packet->swin[i] == 0)
  227. ArtNode.swin[i] = factory_swin[i];
  228. }
  229.  
  230. if(packet->subnet & 0x80)
  231. ArtNode.sub = packet->subnet - 0x80;
  232. else if(packet->subnet == 0)
  233. ArtNode.sub = factory_subnet;
  234.  
  235. // change reply values
  236. fill_art_poll_reply (&ArtPollReply, &ArtNode);
  237. // send ArtPollReply
  238. send_reply(UNICAST, (uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
  239. }
  240.  
  241. void send_reply(uint8_t mode_broadcast, uint8_t *packet, uint16_t size)
  242. {
  243. if(mode_broadcast == 1) // send broadcast packet
  244. {
  245. Udp.sendPacket(packet, size, ArtNode.broadcastIp, ArtNode.remotePort);
  246. }
  247. else // send unicast packet to controller
  248. {
  249. Udp.sendPacket(packet, size, ArtNode.remoteIp, ArtNode.remotePort);
  250. }
  251. }
  252.  
  253. void fill_art_node(artnet_node_t *node)
  254. {
  255. //fill to 0's
  256. memset (node, 0, sizeof(node));
  257.  
  258. //fill data
  259. memcpy (node->mac, factory_mac, 6); // the mac address of node
  260. memcpy (node->localIp, factory_localIp, 4); // the IP address of node
  261. memcpy (node->broadcastIp, factory_broadcastIp, 4); // broadcast IP address
  262. memcpy (node->gateway, factory_gateway, 4); // gateway IP address
  263. memcpy (node->subnetMask, factory_subnetMask, 4); // network mask
  264. memcpy (node->swout, factory_swout, 4);
  265. memcpy (node->swin, factory_swin, 4);
  266.  
  267. memcpy (node->shortname, factory_shortname, sizeof(factory_shortname));
  268. memcpy (node->longname, factory_longname, sizeof(factory_longname));
  269.  
  270. sprintf((char *)node->id, "Art-Net\0");
  271.  
  272. memset (node->porttypes, 0x80, 4);
  273. memset (node->goodinput, 0x08, 4);
  274.  
  275. #if defined(USE_UNIVERSE_0)
  276. node->goodoutput [0] = 0x80;
  277. #endif
  278.  
  279. #if defined(USE_UNIVERSE_1)
  280. node->goodoutput [1] = 0x80;
  281. #endif
  282.  
  283. #if defined(USE_UNIVERSE_2)
  284. node->goodoutput [2] = 0x80;
  285. #endif
  286.  
  287. #if defined(USE_UNIVERSE_3)
  288. node->goodoutput [3] = 0x80;
  289. #endif
  290.  
  291. node->etsaman[0] = 0; // The ESTA manufacturer code.
  292. node->etsaman[1] = 0; // The ESTA manufacturer code.
  293. node->localPort = 0x1936; // artnet UDP port is by default 6454 (0x1936)
  294. node->verH = 1; // high byte of Node firmware revision number.
  295. node->ver = 0; // low byte of Node firmware revision number.
  296. node->ProVerH = 0; // high byte of the Art-Net protocol revision number.
  297. node->ProVer = 14; // low byte of the Art-Net protocol revision number.
  298. node->subH = 0; // high byte of the Node Subnet Address
  299. node->sub = factory_subnet; // low byte of the Node Subnet Address
  300. node->oemH = 0; // high byte of the oem value.
  301. node->oem = 0xFF; // low byte of the oem value. (0x00FF = developer code)
  302. node->ubea = 0; // This field contains the firmware version of the User Bios Extension Area (UBEA). 0 if not used
  303. node->status = 0x08;
  304. node->swvideo = 0;
  305. node->swmacro = 0;
  306. node->swremote = 0;
  307. node->style = 0; // StNode style - A DMX to/from Art-Net device
  308. }
  309.  
  310. void fill_art_poll_reply(artnet_reply_t *poll_reply, artnet_node_t *node)
  311. {
  312. //fill to 0's
  313. memset (poll_reply, 0, sizeof(poll_reply));
  314.  
  315. //copy data from node
  316. memcpy (poll_reply->id, node->id, sizeof(poll_reply->id));
  317. memcpy (poll_reply->ip, node->localIp, sizeof(poll_reply->ip));
  318. memcpy (poll_reply->mac, node->mac, sizeof(poll_reply->mac));
  319. memcpy (poll_reply->shortname, node->shortname, sizeof(poll_reply->shortname));
  320. memcpy (poll_reply->longname, node->longname, sizeof(poll_reply->longname));
  321. memcpy (poll_reply->nodereport, node->nodereport, sizeof(poll_reply->mac));
  322. memcpy (poll_reply->porttypes, node->porttypes, sizeof(poll_reply->porttypes));
  323. memcpy (poll_reply->goodinput, node->goodinput, sizeof(poll_reply->goodinput));
  324. memcpy (poll_reply->goodoutput, node->goodoutput, sizeof(poll_reply->goodoutput));
  325. memcpy (poll_reply->swin, node->swin, sizeof(poll_reply->swin));
  326. memcpy (poll_reply->swout, node->swout, sizeof(poll_reply->swout));
  327. memcpy (poll_reply->etsaman, node->etsaman, sizeof(poll_reply->etsaman));
  328.  
  329. sprintf((char *)poll_reply->nodereport, "%i DMX output universes active.\0", node->numbports);
  330.  
  331. poll_reply->opCode = 0x2100; // ARTNET_REPLY
  332. poll_reply->port = node->localPort;
  333. poll_reply->verH = node->verH;
  334. poll_reply->ver = node->ver;
  335. poll_reply->subH = node->subH;
  336. poll_reply->sub = node->sub;
  337. poll_reply->oemH = node->oemH;
  338. poll_reply->oem = node->oem;
  339. poll_reply->status = node->status;
  340. poll_reply->numbportsH = node->numbportsH;
  341. poll_reply->numbports = node->numbports;
  342. poll_reply->swvideo = node->swvideo;
  343. poll_reply->swmacro = node->swmacro;
  344. poll_reply->swremote = node->swremote;
  345. poll_reply->style = node->style;
  346. }
  347. /*
  348. void fill_art_ipprog_reply(artnet_ipprog_reply_t *ipprog_reply, artnet_node_t *node)
  349. {
  350. //fill to 0's
  351. memset (ipprog_reply, 0, sizeof(ipprog_reply));
  352.  
  353. //copy data from node
  354. memcpy (ipprog_reply->id, node->id, sizeof(ipprog_reply->id));
  355.  
  356. ipprog_reply->ProgIpHi = node->localIp[0];
  357. ipprog_reply->ProgIp2 = node->localIp[1];
  358. ipprog_reply->ProgIp1 = node->localIp[2];
  359. ipprog_reply->ProgIpLo = node->localIp[3];
  360.  
  361. ipprog_reply->ProgSmHi = node->subnetMask[0];
  362. ipprog_reply->ProgSm2 = node->subnetMask[1];
  363. ipprog_reply->ProgSm1 = node->subnetMask[2];
  364. ipprog_reply->ProgSmLo = node->subnetMask[3];
  365.  
  366. ipprog_reply->OpCode = 0xF900; //ARTNET_IPREPLY
  367. ipprog_reply->ProVerH = node->ProVerH;
  368. ipprog_reply->ProVer = node->ProVer;
  369. ipprog_reply->ProgPortHi = node->localPort >> 8;
  370. ipprog_reply->ProgPortLo =(node->localPort & 0xFF);
  371. }
  372. */
Add Comment
Please, Sign In to add comment