Author Topic: [AVR] Basic WS2811 interfacing (addressable RGB leds)  (Read 10829 times)

0 Members and 1 Guest are viewing this topic.

Offline expertmaxTopic starter

  • Regular Contributor
  • *
  • Posts: 51
[AVR] Basic WS2811 interfacing (addressable RGB leds)
« on: November 23, 2014, 11:18:46 pm »
Hi everyone!

After seeing the FastLED library for the Arduino, I thought I would do my own version but using the WS2812B and using a barebone AVR.

This is what my code looks like now :

http://pastebin.com/d2ph6sHh

This is supposed to show on a 16x16 led grid a completely red output.

Am I in the right path?

Thanks

(I don't have a WS2812B with me, eBay Chinese sellers ought to be slow)
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2829
  • Country: nz
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #1 on: November 23, 2014, 11:33:55 pm »
Somewhat.

The on-the-wire protocol for WS2812B has quite precise timing requirements - see

http://www.adafruit.com/datasheets/WS2812B.pdf

Bits are sent as follows:

- A zero bit is sent as 0.4us high, followed by a 0.85us low
- A one bit is sent as 0.8us high, followed by a 0.45us low

These have to be sent with   +/- 0.15us accuracy, and all bits for all LEDs have to be sent back-to- back. For 255 LEDs this will involve sending 6,120 of data bits without a hiccup.

You will most likely have to resort to assembler to achieve this, and you will definitely have to disable interrupts  during the transfer.
« Last Edit: November 23, 2014, 11:38:45 pm by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline expertmaxTopic starter

  • Regular Contributor
  • *
  • Posts: 51
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #2 on: November 23, 2014, 11:46:24 pm »
Would you happen to know what is the ASM code I should type in instead of that bloating C code?

As a beginner in C, I cannot imagine learning ASM just for that particular project (anyway if it's not working, I'll have to use the FastLED library).

Based on the datasheet, here are the changes I made to the code :

http://pastebin.com/k793ZQm8
« Last Edit: November 24, 2014, 12:00:59 am by expertmax »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #3 on: November 24, 2014, 12:07:27 am »
Quote
Am I in the right path?

You would get there, but not as easily.

Take a look at the datasheet and try to code to it at a logic level.

For example: you will need to write a piece of code that send '0' and '1'; To do that, you will need to delay some, in about 0.4us blocks (on a 8MIPS avr, that's about 3 NOPs.

so I would do this instead:

Code: [Select]
#define WS2822_DLY()  {NOP(); NOP(); NOP();}  //delay 0.4us

//send '1' bit
#define WS2822_SEND1() do {PIN_SET(WS2822_PORT, WS2822_PIN); WS2822_DLY(); WS2822_DLY(); PIN_CLR(WS2822_PORT, WS2822_PORT); WS2822_DLY();} while (0)

//send '0' bit
#define WS2822_SEND0() do {PIN_SET(WS2822_PORT, WS2822_PIN); WS2822_DLY(); PIN_CLR(WS2822_PORT, WS2822_PIN); WS2822_DLY(); WS2822_DLY();} while (0)

//send 8-bits
void ws2822_send(uint8_t dat) {
  uint8_t mask = 0x80; //msb first
  do {
    //may need to disable interrupts here
    if (dat & mask) WS2822_SEND1();
    else WS2822_SEND0();
    //if interrupt is previously disabled, enable it here
    mask = mask >> 1;
  } while (mask);
}

//send rgb
#define ws2822_rgb(r, g, b) do {ws2822_send(g); ws2822_send(r); ws2822_send(b);} while (0)

You can compare it vs. the datasheet and the structure would be quite logical.

Additional high level routines can be written based on those little modules, like sending frames.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #4 on: November 24, 2014, 12:08:56 am »
That's the big-bang approach. You could also use other hardware modules, like spi, to send data, without having the mcu working so hard on each bit/byte/frame.
================================
https://dannyelectronics.wordpress.com/
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2829
  • Country: nz
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #5 on: November 24, 2014, 12:19:23 am »
Would you happen to know what is the ASM code I should type in instead of that bloating C code?

As a beginner in C, I cannot imagine learning ASM just for that particular project (anyway if it's not working, I'll have to use the FastLED library).

Based on the datasheet, here are the changes I made to the code :

http://pastebin.com/k793ZQm8

You might be biting off more than you can chew at the moment, but here is how I would structure the code if I was writing in pure assembler:

Code: [Select]
   ; Send the reset pulse
   set output bit low;
   wait for 50us;   - send the reset pulse

   ; Set up for the transfer
   disable interrupts
   Set counter register to 0
   set mask register to 128
   jump start_sending

next_bit:
   NOPs to wait for 0.45ns       
   increment counter register
   roll mask one bit to the left  ; set the mask to the next bit.

start_sending:
   set output bit high
   test if counter = 255*3
   If counter does = 255*3 then jump all_done

   NOPs to wait for initial 0.4ns             ; All bits have high for 0.4ns at the start
   AND mask with data[counter]
   jump one_bit

zero_bit;
   set output bit low                 ; Have already sent the 0.4us of high
   NOPs to wait for 0.40ns       
   jump next_bit

one_bit:
   NOPs to wait for 0.40ns       ; Keep the signal higher longer
   set output bit low
   jump next_bit

all_done:
   set output bit low    ; Optional - start the reset pulse.
   enable interrupts
   return

The code is structured so that it is easy to ensure that all paths through the source will have constant time.

I would then count cycles and tune the numbers of NOPs to get the timing correct, or maybe use a oscilloscope and tune by observation.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline expertmaxTopic starter

  • Regular Contributor
  • *
  • Posts: 51
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #6 on: November 24, 2014, 12:27:51 am »
Ah, so basically the only difference between your code and my code is the use of NOPs...

This project will have no interrupt enabled (as you may notice in the code), it will run at 16 Mhz, will display one "image" every minute (so FPS is far from being important here) and will not monitor external events (such as ADCs and Timers).

The next thing to do is to hookup my logic analyser (Saleae to the rescue) and wait until the dreaded WS2812 arrives.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #7 on: November 24, 2014, 12:48:56 am »
Quote
so basically the only difference between your code and my code is the use of NOPs...

The use of nops is trivial and of zero importance.

What's important is the way to code.
================================
https://dannyelectronics.wordpress.com/
 

Offline expertmaxTopic starter

  • Regular Contributor
  • *
  • Posts: 51
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #8 on: November 24, 2014, 02:36:00 am »
Sorry for my ignorance but I don't see how using macros will help my code.

Again, sorry for my ignorance. I'm not a EE student I'm just a hobbyist.

EDIT: I cannot for the life of me find my freakin' Logic Analyzer. I'll see what the timings are, if that full 3 channel 256 led framing is perfect (cannot detect any glitches though) it is going to stay like that, I'll die ignorant.
« Last Edit: November 24, 2014, 04:20:49 am by expertmax »
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4284
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #9 on: November 24, 2014, 08:37:52 am »
If you indeed require a 0.15us accuracy you're in an range of 2 clock ticks.
Use SPI instead, it is either 30% or 60% of set bits.

NXP's SGPIO would be ideal for this.
« Last Edit: November 24, 2014, 08:50:11 am by Jeroen3 »
 

Offline BloodyCactus

  • Frequent Contributor
  • **
  • Posts: 482
  • Country: us
    • Kråketær
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #10 on: November 24, 2014, 01:24:35 pm »
the timing is not as tight as the datasheet expects;

here is an awesome writeup on the variants

https://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/

« Last Edit: November 24, 2014, 04:16:41 pm by BloodyCactus »
-- Aussie living in the USA --
 

Offline expertmaxTopic starter

  • Regular Contributor
  • *
  • Posts: 51
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #11 on: November 24, 2014, 04:10:58 pm »
If you indeed require a 0.15us accuracy you're in an range of 2 clock ticks.
Use SPI instead, it is either 30% or 60% of set bits.

NXP's SGPIO would be ideal for this.

Can you provide me with a small snippet of code that would initialise the SPI master and the divider + the code to send data?

Thank you!
 

Offline sca

  • Regular Contributor
  • *
  • Posts: 68
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #12 on: November 24, 2014, 04:33:24 pm »
The Signal Path has a recent vid on these addressable LEDs - worth watching.

sca
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2829
  • Country: nz
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #13 on: November 24, 2014, 05:26:37 pm »
I hauled out the oscilloscope and an Arduino last night and played around to generate an in-spec '1' and zero pulse, just to see how much slack there is.

It would be quite easy, if only I could understand GCC's inline assembler options!

All the code would have to be done in one function, as there isn't enough time for any call/return overhead...

Code: [Select]
void outputWS2812Bbits(void)
{
    asm volatile("cli"::);    // Disable interrupts
    // Send a zero bit
    __asm__("sbi 5,  4\n\t");     // Set port b bit 4 Arduino pin 12
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("cbi 5, 4\n\t");      // clear port b bit 4
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // a pause

    // Send a one bit
    __asm__("sbi 5,  4\n\t");     // Set port b bit 4
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("cbi 5, 4\n\t");      // clear port b bit 4
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // A pause
    __asm__("nop\n\t");           // a pause
   
    asm volatile("sei"::); // Enable interrupts
}
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8549
  • Country: us
    • SiliconValleyGarage
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #14 on: November 24, 2014, 05:35:00 pm »
i'm amazed nobody has stuffed that crap in a small cpld yet. you could feed data in parallel and have the cpld handle all the critical timing and other crap.
Plus you could hook up mulitple chains to the cpld and write alternate bytes. the throughput could be phenomenal.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2829
  • Country: nz
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #15 on: November 25, 2014, 08:11:48 am »
So, the challenge got to me, and I spent the night learning AVRGCC and wrote a simple WS2812b driver - it is all in one file, and checking timing on the scope they are with +/-  50 ns.

Here's the code - it is not the most beautiful or compact code out there, but it does weigh in at about 300 bytes.:

Code: [Select]
/******************************************
* ws2812b_demo.c
*
* Author : Mike Field <hamster@snap.net.nz<
*
* A really simple driver for WS2812B LEDs for
* the Arduino Uno. Must be running at 16MHz.
*
*********************************************/

#define OUTPUT_PIN 12

unsigned char leds[5][3];

void outputWS2812Bbytes(unsigned char (*leds)[3], unsigned char length)
{
delay(1);
  asm volatile(
  " cli \n\t" // Disable interrupts
  " mov 18,%1\n\t"  // Copy length
  " add %1, 18\n\t" // Add it back
  " add %1, 18\n\t" // Add it back, so it is now x3 what it was
  "L_next%=:" "\n\t"
  ///////////////////////////////////////////////////////////
  // Bit 7
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 128 \n\t" // Test the bit - one cycle
  " BRNE L_bit7%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  "L_bit7%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause

  ///////////////////////////////////////////////////////////
  // Bit 6
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 64 \n\t" // Test the bit - one cycle
  " BRNE L_bit6_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit6_1_%=  \n\t"
  "L_bit6_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit6_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
 
  ///////////////////////////////////////////////////////////
  // Bit 5
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 32 \n\t" // Test the bit - one cycle
  " BRNE L_bit5_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit5_1_%=  \n\t"
  "L_bit5_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit5_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
 
  ///////////////////////////////////////////////////////////
  // Bit 4
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 16 \n\t" // Test the bit - one cycle
  " BRNE L_bit4_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit4_1_%=  \n\t"
  "L_bit4_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit4_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
 
 
  ///////////////////////////////////////////////////////////
  // Bit 3
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 8 \n\t" // Test the bit - one cycle
  " BRNE L_bit3_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit3_1_%=  \n\t"
  "L_bit3_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit3_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
 
  ///////////////////////////////////////////////////////////
  // Bit 2
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 4 \n\t" // Test the bit - one cycle
  " BRNE L_bit2_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit2_1_%=  \n\t"
  "L_bit2_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit2_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause

  ///////////////////////////////////////////////////////////
  // Bit 1
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z \n\t" // Load and post increment - two cycles
  " ANDI 18, 2 \n\t" // Test the bit - one cycle
  " BRNE L_bit1_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit1_1_%=  \n\t"
  "L_bit1_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit1_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
 
 
  ///////////////////////////////////////////////////////////
  // Bit 0
  " SBI 5, 4 \n\t" // Set port b bit 4 Arduino pin 12
  " NOP \n\t" // A pause
  " LD 18, Z+ \n\t" // Load and post increment - two cycles
  " ANDI 18, 1 \n\t" // Test the bit - one cycle
  " BRNE L_bit0_0_%= \n\t" // Skip the clear if the bit is set
  " CBI 5, 4 \n\t" // clear port b bit 4
  " JMP L_bit0_1_%=  \n\t"
  "L_bit0_0_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  "L_bit0_1_%=:" "\n\t"
  " NOP \n\t" // A pause
  " NOP \n\t" // A pause
  " cbi 5, 4 \n\t" // clear port b bit 4
  " SUBI %1,1 \n\t" // Decrement the count
  " BREQ L_done%= \n\t" // Exit when finished
  " JMP L_next%= \n\t" // Jump back if we still have more to do

  // All Finshed
  "L_done%=: \n\t"
  " sei \n\t"
    : : "z" (leds),  "d" (length));
}

void setup() {
  // put your setup code here, to run once:
  pinMode(OUTPUT_PIN,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  leds[0][0] = 0x3F;
  leds[0][1] = 0x3F;
  leds[0][2] = 0x3F;

  leds[1][0] = 0x6F;
  leds[1][1] = 0;
  leds[1][2] = 0;

  leds[2][0] = 0;
  leds[2][1] = 0x6F;
  leds[2][2] = 0;

  leds[3][0]  = 0;
  leds[3][1] = 0;
  leds[3][2] = 0x6F;

  leds[4][0] = 0x3F;
  leds[4][1] = 0x3F;
  leds[4][2] = 0x3F;
 
  outputWS2812Bbytes(leds,5);
}

« Last Edit: November 25, 2014, 08:37:39 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline BurtyB

  • Regular Contributor
  • *
  • Posts: 66
  • Country: gb
    • 8086 Consultancy
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #16 on: November 27, 2014, 12:16:38 am »
i'm amazed nobody has stuffed that crap in a small cpld yet. you could feed data in parallel and have the cpld handle all the critical timing and other crap.
Plus you could hook up mulitple chains to the cpld and write alternate bytes. the throughput could be phenomenal.

Another option would be the Teensy 3.1 + OctoWS2811 [+ 74HCT245] with the associated library which uses PWM+DMA to handle the timings for 8 channels leaving the CPU mostly free for other tasks (I'm planning to use it for a WS2812B based 3D LED Cube).
 

Offline aon

  • Contributor
  • Posts: 30
  • Country: fi
Re: [AVR] Basic WS2811 interfacing (addressable RGB leds)
« Reply #17 on: November 28, 2014, 07:54:24 am »
i'm amazed nobody has stuffed that crap in a small cpld yet. you could feed data in parallel and have the cpld handle all the critical timing and other crap.
Plus you could hook up mulitple chains to the cpld and write alternate bytes. the throughput could be phenomenal.

Another option would be the Teensy 3.1 + OctoWS2811 [+ 74HCT245] with the associated library which uses PWM+DMA to handle the timings for 8 channels leaving the CPU mostly free for other tasks (I'm planning to use it for a WS2812B based 3D LED Cube).

There's also 0xWS2812 for STM32F10x that uses a similar approach. I've got a "port" of it running on STM32F030 - the WS2812B driver and a DMX512 receiver seem to just about fit in a STM32F030F4P6 which is a pretty inexpensive way to drive 8 parallel strings of leds, although the level shifting parts and a 3.3V supply pretty much double the cost.

Doing it in a CPLD did cross my mind, it's something I'll probably try to do as a learning experience once I get into learning a HDL.
« Last Edit: November 28, 2014, 07:57:00 am by aon »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf