#define WS2812B_pin 8
#define numberOfLEDs 60
byte RGB[120];
void RGB_update(byte LED, byte RED,byte GREEN,byte BLUE);
void setup() {
Serial.begin(1000000);
delay(1000);
pinMode(WS2812B_pin, OUTPUT);
}
int serialGlediator() {
while (!Serial.available()) {}
return Serial.read();
}
void loop() {
//while (serialGlediator() != 1) {}
for (int i=0; i < numberOfLEDs; i++) {
RGB_update(i,serialGlediator(),serialGlediator(),serialGlediator());
}
}
void RGB_update(int LED, byte RED, byte GREEN, byte BLUE) {
// LED is the LED number starting with 0
// RED, GREEN, BLUE is the brightness 0..255 setpoint for that LED
byte ExistingPort, WS2812pinHIGH;//local variables here to speed up pinWrites
if(LED>=0){//map the REG GREEN BLUE Values into the RGB[] array
RGB[LED * 3] = GREEN;
RGB[LED * 3 + 1] = RED;
RGB[LED * 3 + 2] = BLUE;
}
noInterrupts();//kill the interrupts while we send the bit stream out...
ExistingPort = PORTB; // save the status of the entire PORT B - let's us write to the entire port without messing up the other pins on that port
WS2812pinHIGH = PORTB | 1; //this gives us a byte we can use to set the whole PORTB with the WS2812 pin HIGH
int bitStream = numberOfLEDs * 3;//total bytes in the LED string
//This for loop runs through all of the bits (8 at a time) to set the WS2812 pin ON/OFF times
for (int i = 0; i < bitStream; i++) {
PORTB = WS2812pinHIGH;//bit 7 first, set the pin HIGH - it always goes high regardless of a 0/1
//here's the tricky part, check if the bit in the byte is high/low then right that status to the pin
// (RGB & B10000000) will strip away the other bits in RGB, so here we'll be left with B10000000 or B00000000
// then it's easy to check if the bit is high or low by AND'ing that with the bit mask ""&& B10000000)"" this gives 1 or 0
// if it's a 1, we'll OR that with the Existing port, thus keeping the pin HIGH, if 0 the pin is written LOW
PORTB = ((RGB & B10000000) && B10000000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//these are NOPS - these let us delay clock cycles for more precise timing
PORTB = ExistingPort;//okay, here we know we have to be LOW regardless of the 0/1 bit state
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//minimum LOW time for pin regardless of 0/1 bit state
// then do it again for the next bit and so on... see the last bit though for a slight change
PORTB = WS2812pinHIGH;//bit 6
PORTB = ((RGB & B01000000) && B01000000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 5
PORTB = ((RGB & B00100000) && B00100000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 4
PORTB = ((RGB & B00010000) && B00010000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 3
PORTB = ((RGB & B00001000) && B00001000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 2
PORTB = ((RGB & B00000100) && B00000100) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 1
PORTB = ((RGB & B00000010) && B00000010) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 0
__asm__("nop\n\t");//on this last bit, the check is much faster, so had to add a NOP here
PORTB = ((RGB & B00000001) && B00000001) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;//note there are no NOPs after writing the pin LOW, this is because the FOR Loop uses clock cycles that we can use instead of the NOPS
}//for loop
interrupts();//enable the interrupts
// all done!
}