Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///////////////////////////////////////
- //
- // WS2811 Test Sketch
- //
- // 04.05.2016: First Version
- // 05.05.2016: Manual timing via NOP doesn't work.
- // Switching to timer2 (PD3)
- // Finally works! https://youtu.be/hwUaI-tJ2UE
- //
- ///////////////////////////////////////
- /* Description of the WS2811 protocol:
- *
- * https://cdn-shop.adafruit.com/datasheets/WS2811.pdf
- *
- * 0 is 0.5µs high, 2µs low
- * 1 is 1.2µs high, 1.3µs low
- * half of those values for the 800kHz modules
- *
- * Timing between bits is less critical - 3µs are ok.
- * >6-9µs leads to reset=latching the data to the LEDs
- *
- * Thus trying bitbang on PD3
- *
- */
- #define LEDNO 50
- #define OFF 4
- #define ON 9
- #define BITLENGTH 20
- uint8_t red = 0;
- uint8_t green = 85;
- uint8_t blue = 170;
- uint8_t leds = 0;
- void setup() {
- DDRD |= (1<<PD3); // set PD3 as Output
- PORTD &= ~(1<<PD3); // set PD3 low
- // disable Arduino lib timer 0
- TCCR0A = 0;
- TCCR0B = 0;
- TCCR2B = 0; // reset TIMER2
- TCCR2A = 0;
- OCR2A = BITLENGTH; // Total length of a bit for WS2811
- for (int i=0; i<LEDNO; i++) {
- send_bits(0, 0, 0);
- }
- delay_us(50);
- }
- inline void set_timer() {
- TIFR2 |= (1<<TOV2); // Alternatively, TOV2 is cleared by writing a logic one to the flag
- while (!(TIFR2 & (1 << TOV2))); // Wait for overflow to occur
- TCNT2 = 0;
- }
- void send_bits(byte red, byte green, byte blue) {
- cli(); // stop interrupts
- TCCR2A = (1 << COM2B1) | (1 << WGM21) | (1 << WGM20); // FastPWM to OCR2A
- // COM2B1: Clear OC2B on Compare Match, set OC2B at BOTTOM
- // WGM21, WGM20: Fast PWM ...
- TCCR2B = (1 << WGM22) | (1 << CS20); // No prescaling; starts PWM
- // WGM22: ... Fast PWM Top OCR2A; CS20 = No prescaler
- // manual unrolling - ugly!
- // red ...
- TCNT2 = 0;
- (red & (1<<7)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<6)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<5)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<4)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<3)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<2)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<1)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (red & (1<<0)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- // green ...
- (green & (1<<7)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<6)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<5)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<4)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<3)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<2)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<1)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (green & (1<<0)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- // blue ...
- (blue & (1<<7)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<6)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<5)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<4)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<3)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<2)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<1)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- set_timer();
- (blue & (1<<0)) ? OCR2B = ON : OCR2B = OFF; // set timer for bit on or off
- TIFR2 |= (1<<TOV2); // Alternatively, TOV2 is cleared by writing a logic one to the flag
- while (!(TIFR2 & (1 << TOV2))); // Wait for overflow to occur
- sei(); // start interrupts
- while (TCNT2 < ON);
- TCCR2B = 0; // Reset TIMER2 again
- TCCR2A = 0; // and switching it off.
- PORTD &= ~(1<<PD3); // set PD3 low
- }
- // --- some weirdo delay function --------------------------------------------
- void delay_us (int16_t us) {
- for (uint16_t i=0; i<us; i++) {
- for (int j=0; j<16; j++) {
- asm volatile ("nop");
- }
- }
- }
- void loop() {
- /*
- for (int i=0; i<LEDNO; i++) {
- red++;
- green++;
- blue++;
- send_bits(red, green, blue);
- }
- delay_us(50);
- delay_us(30000);
- */
- // /*
- for (int k=0; k<3; k++) {
- switch (k) {
- case 0: red = 255; green = 0; blue = 0; break;
- case 1: red = 0; green = 255; blue = 0; break;
- case 2: red = 0; green = 0; blue = 255; break;
- }
- for (int i=0; i<LEDNO; i++) {
- for (int j=0; j<LEDNO; j++) {
- (i==j) ? send_bits(red, green, blue) : send_bits(0, 0, 0);
- }
- delay_us(50);
- delay_us(10000);
- }
- }
- // */
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement