Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add APA104 #14

Open
imShara opened this issue May 19, 2016 · 8 comments
Open

Add APA104 #14

imShara opened this issue May 19, 2016 · 8 comments

Comments

@imShara
Copy link

imShara commented May 19, 2016

I'm trying to add APA104 support with another timings (T0H: 0.35µs, T0L: 1.36µs, T1H: 1.36µs, T1L: 0.35µs).

Can you explain your I²S frequency setup formula?

12000000 / (div * bestbck * 2)

WS2812B timings is
T0H: 0.4µs, T0L: 0.85µs, T1H: 0.8µs, T1L: 0.45µs
1,25µs per led / 3 sample = 0,416 µs per sample

Default settings is

define WS2812_THREE_SAMPLE

define WS_I2S_BCK 22

define WS_I2S_DIV 4

Then..
12000000 Hz — system frequency
2 — I²S frequency (half of system frequency)
4 — I²S frequency divider
22 — secondary I²S frequency divider

12000000 / (4 * 22 * 2) = 68181,81 Hz I²S bit speed
68181,81 / 1000000 = 0,0681 µs per bit

Aw, but there is 0,416 µs per sample.. Something goes wrong.

And why you need bitpattern arrays?

@cnlohr
Copy link
Owner

cnlohr commented May 19, 2016

I think the comment is wrong as the actual system frequency is 160MHz and I don't know where the other 2 came from. 160/(22*4) = 909kHz or .55us per line bit, or 1.65us per actual bit (3 line bits make an LED bit) WILL HAVE TO EXPERIMENT TO VERIFY!!!

This is concerning as .55us is right on the hairy edge for a logical '0.' I don't know how I didn't revisit this earlier. I think you should be using foursample based on your numbers, though. Foursample works a lot better and makes more sense. In fact, just selecting FOURSAMPLE will probably give you the right timings.

@imShara
Copy link
Author

imShara commented May 19, 2016

@cnlohr, 160Mhz you mean

160000000 / (22 * 4) = 1818181,81818 Hz
1818181,81818 / 1000000 = 1,81 µs per bit

Right?

Ok, for FOURSAMPLE mode:

There is 4 I²S bits for each WS2812 bits, then we need I²S speed 1,25µs / 4 = 0,3125 µs per bit

160000000 / (17 * 4) = 2352941,17647 Hz
2352941,17647 / 1000000 = 2,35 µs per bit

In fact, just selecting FOURSAMPLE will probably give you the right timings.

Nope, tried

@cnlohr
Copy link
Owner

cnlohr commented May 19, 2016

Your divisors are backwards on your math. IT would be 1,000,000 / 1,818,181 = 0.55 us per bit for the first and .425us per bit on the second.

@imShara
Copy link
Author

imShara commented May 19, 2016

Oh, you are right, thanks. Wait a commit.

@imShara
Copy link
Author

imShara commented May 19, 2016

Nope, it's not working proper with four sample mode with BCK = 14 (0.35µs per i2s bit, 1,4µs per led bit). Other numbers not helps too. Then, I think I need 5 bit mode (0.35µs per i2s bit, 1.75 per led bit). This is nearest numbers to datasheet values.

What is your bitpattern arrays? Array elements are led byte representation e.g 100 110 110 100 for three byte mode and e.g 1000 1110 1000 1110 for four byte mode. But why you use it? For converting received HEX value representation directly to i2s representation?

#ifdef WS2812_THREE_SAMPLE

    static const uint16_t bitpatterns[16] = {
        0b100100100100, 0b100100100110, 0b100100110100, 0b100100110110,
        0b100110100100, 0b100110100110, 0b100110110100, 0b100110110110,
        0b110100100100, 0b110100100110, 0b110100110100, 0b110100110110,
        0b110110100100, 0b110110100110, 0b110110110100, 0b110110110110,
    };

#elif defined(WS2812_FOUR_SAMPLE)

    //Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
    static const uint16_t bitpatterns[16] = {
        0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
        0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
        0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
        0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
    };

#endif
#elif defined(WS2812_FOUR_SAMPLE)

    uint16_t * bufferpl = (uint16_t*)&i2sBlock[0];

    if( buffersize * 4 > WS_BLOCKSIZE ) return;

    for( place = 0; place < buffersize; place++ )
    {
        uint8_t btosend = buffer[place];
        *(bufferpl++) = bitpatterns[(btosend&0x0f)];
        *(bufferpl++) = bitpatterns[(btosend>>4)&0x0f];
    }

#endif

@imShara
Copy link
Author

imShara commented May 20, 2016

@cnlohr, what data should be in the bufferpl array at the out of ws2812_push function?

Trying to make manual-filled 5-sample led sequence, but it's so laggy - is it right data?

void ws2812_push(uint8_t *buffer, uint16_t buffersize) {
    uint8_t *bufferpl = (uint8_t*) & i2sBlock[0];

    // LED 0 OFF
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // LED 0

    // LED 1 GREEN
    // \xFF
    *(bufferpl++) = 0b11110111;
    *(bufferpl++) = 0b10111101;
    *(bufferpl++) = 0b11101111;
    *(bufferpl++) = 0b01111011;
    *(bufferpl++) = 0b11011110;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // LED 1

    // LED 2 RED
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \xFF
    *(bufferpl++) = 0b11110111;
    *(bufferpl++) = 0b10111101;
    *(bufferpl++) = 0b11101111;
    *(bufferpl++) = 0b01111011;
    *(bufferpl++) = 0b11011110;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // LED 2

    // LED 3 BLUE
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \x00
    *(bufferpl++) = 0b10000100;
    *(bufferpl++) = 0b00100001;
    *(bufferpl++) = 0b00001000;
    *(bufferpl++) = 0b01000010;
    *(bufferpl++) = 0b00010000;
    // \xFF
    *(bufferpl++) = 0b11110111;
    *(bufferpl++) = 0b10111101;
    *(bufferpl++) = 0b11101111;
    *(bufferpl++) = 0b01111011;
    *(bufferpl++) = 0b11011110;
    // LED 3
}

@imShara
Copy link
Author

imShara commented May 20, 2016

Selfanswer — yes, I'm right. But I doubt in frequency formula. Need oscilloscope.

@cnlohr
Copy link
Owner

cnlohr commented May 22, 2016

Hey, sorry, just getting back to this now. I recommend use of a logic analyzer on this one. You can pick up pretty good ones for $15 or so. I really think you should be able to use the 4-timing though the clock divisors might need to be different. Also, you'll need to check a bunch of other things like making sure the voltage is good etc. I guess you could use a scope to make sure there signal looks clear and you don't have ground loops, etc.

@con-f-use con-f-use changed the title Trying to add APA104. Please, explain your formula Add APA104 Aug 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants