/** * 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; }
/** * 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; }
/** * 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; }