/**
 * Shut down DMA, PWM, and cleanup memory.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
void ws2811_fini(ws2811_t *ws2811)
{
    ws2811_wait(ws2811);
    stop_pwm(ws2811);

    unmap_registers(ws2811);

    ws2811_cleanup(ws2811);
}
/**
 * Render the PWM DMA buffer from the user supplied LED arrays and start the DMA
 * controller.  This will update all LEDs on both PWM channels.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
int ws2811_render(ws2811_t *ws2811)
{
    volatile uint8_t *pwm_raw = ws2811->device->pwm_raw;
    int bitpos = 31;
    int i, j, k, l, chan;

    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)         // Channel
    {
        ws2811_channel_t *channel = &ws2811->channel[chan];
        int wordpos = chan;
        int scale   = (channel->brightness & 0xff) + 1;

        for (i = 0; i < channel->count; i++)                // Led
        {
            uint8_t color[] =
            {
                (((channel->leds[i] >> 8)  & 0xff) * scale) >> 8, // green
                (((channel->leds[i] >> 16) & 0xff) * scale) >> 8, // red
                (((channel->leds[i] >> 0)  & 0xff) * scale) >> 8, // blue
            };

            for (j = 0; j < (int) ARRAY_SIZE(color); j++)        // Color
            {
                for (k = 7; k >= 0; k--)                   // Bit
                {
                    uint8_t symbol = SYMBOL_LOW;

                    if (color[j] & (1 << k))
                    {
                        symbol = SYMBOL_HIGH;
                    }

                    if (channel->invert)
                    {
                        symbol = ~symbol & 0x7;
                    }

                    for (l = 2; l >= 0; l--)               // Symbol
                    {
                        uint32_t *wordptr = &((uint32_t *)pwm_raw)[wordpos];

                        *wordptr &= ~(1 << bitpos);
                        if (symbol & (1 << l))
                        {
                            *wordptr |= (1 << bitpos);
                        }

                        bitpos--;
                        if (bitpos < 0)
                        {
                            // Every other word is on the same channel
                            wordpos += 2;

                            bitpos = 31;
                        }
                    }
                }
            }
        }
    }

    // Wait for any previous DMA operation to complete.
    if (ws2811_wait(ws2811))
    {
        return -1;
    }

    dma_start(ws2811);

    return 0;
}
Beispiel #3
0
/**
 * Render the PWM DMA buffer from the user supplied LED arrays and start the DMA
 * controller.  This will update all LEDs on both PWM channels.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
int ws2811_render(ws2811_t *ws2811)
{
    volatile uint8_t *pwm_raw = ws2811->device->pwm_raw;
    int bitpos = 31;
    int i, k, l, chan;
    unsigned j;

    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)         // Channel
    {
        ws2811_channel_t *channel = &ws2811->channel[chan];
        int wordpos = chan;
        int scale   = (channel->brightness & 0xff) + 1;
        int wshift  = (channel->strip_type >> 24) & 0xff;
        int rshift  = (channel->strip_type >> 16) & 0xff;
        int gshift  = (channel->strip_type >> 8)  & 0xff;
        int bshift  = (channel->strip_type >> 0)  & 0xff;

//printf ("chan %d, wshift %d rshift %d gshift %d bshift %d \n",chan, wshift,rshift, gshift, bshift);

        for (i = 0; i < channel->count; i++)                // Led
        {
            uint8_t color[] =
            {
                (((channel->leds[i] >> rshift) & 0xff) * scale) >> 8, // red
                (((channel->leds[i] >> gshift) & 0xff) * scale) >> 8, // green
                (((channel->leds[i] >> bshift) & 0xff) * scale) >> 8, // blue
                (((channel->leds[i] >> wshift) & 0xff) * scale) >> 8, // white
            };


//if (i<10) printf ("i %3d red %02x green %02x blue %02x white %02x\n", i, color[0], color[1], color[2], color[3]);
            int array_size = 3;	// assume 3 for RGB
            if (channel->strip_type == SK6812_STRIP_RGBW) {
		array_size = 4;	// this strip needs 4 - RGB + W
            }

            for (j = 0; j < array_size; j++)        // Color
            {
                for (k = 7; k >= 0; k--)                   // Bit
                {
                    uint8_t symbol = SYMBOL_LOW;

                    if (color[j] & (1 << k))
                    {
                        symbol = SYMBOL_HIGH;
                    }

                    for (l = 2; l >= 0; l--)               // Symbol
                    {
                        uint32_t *wordptr = &((uint32_t *)pwm_raw)[wordpos];

                        *wordptr &= ~(1 << bitpos);
                        if (symbol & (1 << l))
                        {
                            *wordptr |= (1 << bitpos);
                        }

                        bitpos--;
                        if (bitpos < 0)
                        {
                            // Every other word is on the same channel
                            wordpos += 2;

                            bitpos = 31;
                        }
                    }
                }
            }
        }
    }

    // Wait for any previous DMA operation to complete.
    if (ws2811_wait(ws2811))
    {
        return -1;
    }

    dma_start(ws2811);

    return 0;
}
Beispiel #4
0
/**
 * Render the PWM DMA buffer from the user supplied LED arrays and start the DMA
 * controller.  This will update all LEDs on both PWM channels.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
int ws2811_render(ws2811_t *ws2811)
{
    volatile uint8_t *pwm_raw = ws2811->device->pwm_raw;
    int bitpos = 31;
    int i, k, l, chan;
    unsigned j;

    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)         // Channel
    {
        ws2811_channel_t *channel = &ws2811->channel[chan];
        int wordpos = chan;
        int scale   = (channel->brightness & 0xff) + 1;
        int wshift  = (channel->strip_type >> 24) & 0xff;
        int rshift  = (channel->strip_type >> 16) & 0xff;
        int gshift  = (channel->strip_type >> 8)  & 0xff;
        int bshift  = (channel->strip_type >> 0)  & 0xff;

        for (i = 0; i < channel->count; i++)                // Led
        {
            uint8_t color[] =
            {
                (((channel->leds[i] >> rshift) & 0xff) * scale) >> 8, // red
                (((channel->leds[i] >> gshift) & 0xff) * scale) >> 8, // green
                (((channel->leds[i] >> bshift) & 0xff) * scale) >> 8, // blue
                (((channel->leds[i] >> wshift) & 0xff) * scale) >> 8, // white
            };
            uint8_t array_size = 3; // Assume 3 color LEDs, RGB

            // If our shift mask includes the highest nibble, then we have 4
            // LEDs, RBGW.
            if (channel->strip_type & SK6812_SHIFT_WMASK)
            {
                array_size = 4;
            }

            for (j = 0; j < array_size; j++)               // Color
            {
                for (k = 7; k >= 0; k--)                   // Bit
                {
                    uint8_t symbol = SYMBOL_LOW;

                    if (color[j] & (1 << k))
                    {
                        symbol = SYMBOL_HIGH;
                    }

                    for (l = 2; l >= 0; l--)               // Symbol
                    {
                        uint32_t *wordptr = &((uint32_t *)pwm_raw)[wordpos];

                        *wordptr &= ~(1 << bitpos);
                        if (symbol & (1 << l))
                        {
                            *wordptr |= (1 << bitpos);
                        }

                        bitpos--;
                        if (bitpos < 0)
                        {
                            // Every other word is on the same channel
                            wordpos += 2;

                            bitpos = 31;
                        }
                    }
                }
            }
        }
    }

    // Wait for any previous DMA operation to complete.
    if (ws2811_wait(ws2811))
    {
        return -1;
    }

    dma_start(ws2811);

    return 0;
}