-
-
Save jshaw/72cd92e729196f1f9d7a5fc89e31e936 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SPI.h> | |
#include <Ethernet.h> | |
#include <EthernetUdp.h> | |
#define USE_OCTOWS2811 | |
#include <OctoWS2811.h> | |
#include <FastLED.h> | |
// enter desired universe and subnet (sACN first universe is 1) | |
#define DMX_SUBNET 0 | |
#define DMX_UNIVERSE 1 //**Start** universe | |
#define DEBUG 1 | |
// Set a unique MAC address for each node. | |
byte gMac[] = {0x74,0x69,0x69,0x2D,0x30,0x15}; | |
EthernetUDP Udp; | |
#define ETHERNET_BUFFER 636 | |
#define CHANNEL_COUNT 16320 //because it divides by 3 nicely | |
#define NUM_LEDS_PER_STRIP 150 | |
#define NUM_STRIPS 8 | |
#define NUM_LEDS NUM_LEDS_PER_STRIP * NUM_STRIPS | |
#define UNIVERSE_COUNT 32 | |
#define LEDS_PER_UNIVERSE 170 // DMX 512 / 3 = 170-ish | |
#define BRIGHTNESS 100 | |
CRGB leds[NUM_LEDS]; | |
// Pin layouts on the teensy 3: | |
// OctoWS2811: 2,14,7,8,6,20,21,5 | |
unsigned char gPacketBuffer[ETHERNET_BUFFER]; | |
int gC = 0; | |
float gFps = 0; | |
unsigned long gCurrentMillis = 0; | |
unsigned long gPreviousMillis = 0; | |
void setup() { | |
pinMode(9, OUTPUT); | |
digitalWrite(9, LOW); // toggle the WIZ820io reset | |
delay(10); | |
digitalWrite(9, HIGH); | |
#ifdef DEBUG | |
Serial.begin(115200); | |
delay(10); // let UART settle | |
#endif | |
/* | |
*** WARNING *** | |
3 big blocks of Memory in use here: | |
The first is your LEDs array - which is going to be over NUM_LEDS_PER_STRIP * NUM_STRIPS * 3 bytes. | |
The second is the buffer that octows2811 is writing out of, which is the same size as above. | |
The third is a buffer that is used to translate/scale the first buffer while octows2811 may still be | |
writing data out of the second buffer. | |
The Teensy 3.2 has only 64K to work with. | |
*/ | |
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP); // block of memory NUM_LEDS_PER_STRIP * 3 | |
LEDS.setBrightness(32); | |
Ethernet.begin(gMac); // DHCP assigned IP | |
Udp.begin(5568); | |
#ifdef DEBUG | |
Serial.print("DHCP ADDr: "); | |
Serial.println(Ethernet.localIP()); | |
#endif | |
lampTest(); | |
} | |
void sacnDMXReceived(unsigned char * pbuff, int count, int unicount) { | |
if (count > CHANNEL_COUNT) count = CHANNEL_COUNT; | |
byte b = pbuff[113]; //DMX Subnet | |
if (b == DMX_SUBNET) { | |
b = pbuff[114]; //DMX Universe | |
#ifdef DEBUG | |
Serial.println(b); | |
#endif | |
if (b >= DMX_UNIVERSE && b <= DMX_UNIVERSE + UNIVERSE_COUNT) { | |
if (pbuff[125] == 0) { //start code must be 0 | |
int ledNumber = (b - DMX_UNIVERSE) * LEDS_PER_UNIVERSE; | |
// sACN packets come in seperate RGB but we have to set each led's RGB value together | |
// this 'reads ahead' for all 3 colours before moving to the next led. | |
#ifdef DEBUG | |
Serial.println("*"); | |
#endif | |
for (int i = 126; i < 126 + count; i = i + 3) { | |
byte red = pbuff[i]; | |
byte green = pbuff[i + 1]; | |
byte blue = pbuff[i + 2]; | |
leds[ledNumber] = CRGB(red, green, blue); | |
#ifdef DEBUG | |
Serial.println(ledNumber); | |
#endif | |
ledNumber++; | |
} | |
#ifdef DEBUG | |
Serial.println(unicount); | |
#endif | |
if (unicount == UNIVERSE_COUNT) { | |
LEDS.show(); | |
} | |
} | |
} | |
} | |
} | |
int checkACNHeaders(unsigned char * messagein, int messagelength) { | |
//Do some VERY basic checks to see if it's an E1.31 packet. | |
//Bytes 4 to 12 of an E1.31 Packet contain "ACN-E1.17" | |
//Only checking for the A and the 7 in the right places as well as 0x10 as the header. | |
//Technically this is outside of spec and could cause problems but its enough checks for us | |
//to determine if the packet should be tossed or used. | |
//This improves the speed of packet processing as well as reducing the memory overhead. | |
//On an Isolated network this should never be a problem.... | |
if (messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) { | |
int addresscount = (byte) messagein[123] * 256 + (byte) messagein[124]; // number of values plus start code | |
return addresscount - 1; //Return how many values are in the packet. | |
} | |
return 0; | |
} | |
void lampTest() { | |
FastLED.setBrightness(BRIGHTNESS); | |
FastLED.clear(); | |
FastLED.show(); | |
for (int i = 0; i < 4; i++) { | |
const struct CRGB colours[4] = { | |
CRGB::Red, | |
CRGB::Green, | |
CRGB::Blue, | |
CRGB::White | |
}; | |
fill_solid(leds, NUM_LEDS, colours[i]); | |
FastLED.show(); | |
FastLED.delay(400); | |
} | |
FastLED.clear(); | |
FastLED.show(); | |
} | |
void loop() { | |
//Process packets | |
int packetSize = Udp.parsePacket(); //Read UDP packet count | |
if (gC >= 10) { | |
gC = 0; | |
} | |
if (packetSize) { | |
#ifdef DEBUG | |
Serial.println(packetSize); | |
#endif | |
Udp.read(gPacketBuffer, ETHERNET_BUFFER); //read UDP packet | |
int count = checkACNHeaders(gPacketBuffer, packetSize); | |
if (count) { | |
#ifdef DEBUG | |
Serial.print("packet size first "); | |
Serial.println(packetSize); | |
#endif | |
gC = gC + 1; | |
// calculate framerate | |
gCurrentMillis = millis(); | |
if (gCurrentMillis > gPreviousMillis) { | |
gFps = 1 / ((gCurrentMillis - gPreviousMillis) * 0.001); | |
} else { | |
gFps = 0; | |
} | |
gPreviousMillis = gCurrentMillis; | |
#ifdef DEBUG | |
if (gFps > 10 && gFps < 500) { // don't show numbers below or over given ammount | |
Serial.println(gFps); | |
} | |
#endif | |
sacnDMXReceived(gPacketBuffer, count, gC); //process data function | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment