Refactored to sk6812; Added white channel
This commit is contained in:
parent
f033119aa8
commit
bca64a858a
|
@ -13,12 +13,12 @@ set(sources
|
||||||
src/main.c
|
src/main.c
|
||||||
src/udpproto.c
|
src/udpproto.c
|
||||||
src/utils.c
|
src/utils.c
|
||||||
src/ws2801.c
|
src/sk6812.c
|
||||||
src/fader.h
|
src/fader.h
|
||||||
src/logger.h
|
src/logger.h
|
||||||
src/udpproto.h
|
src/udpproto.h
|
||||||
src/utils.h
|
src/utils.h
|
||||||
src/ws2801.h
|
src/sk6812.h
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|
40
src/fader.c
40
src/fader.c
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ws2801.h"
|
#include "sk6812.h"
|
||||||
|
|
||||||
#include "fader.h"
|
#include "fader.h"
|
||||||
|
|
||||||
|
@ -11,18 +11,20 @@ uint32_t numModules;
|
||||||
float fadestep = 1;
|
float fadestep = 1;
|
||||||
double nextFrame;
|
double nextFrame;
|
||||||
|
|
||||||
int somethingChanged = 0; // indicates when a ws2801 update is required
|
int somethingChanged = 0; // indicates when a sk6812 update is required
|
||||||
|
|
||||||
static const double interval = 0.01f;
|
static const double interval = 0.01f;
|
||||||
|
|
||||||
struct Colour {
|
struct Colour {
|
||||||
float red, green, blue; // value range is 0.0 to 255.0
|
float red, green, blue, white; // value range is 0.0 to 255.0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Colour *curColour;
|
struct Colour *curColour;
|
||||||
struct Colour *targetColour;
|
struct Colour *targetColour;
|
||||||
|
|
||||||
int fader_init(uint32_t nMod)
|
struct sk6812_ctx *ledCtx; // global context for the one strip we control
|
||||||
|
|
||||||
|
int fader_init(uint32_t nMod, struct sk6812_ctx *ctx)
|
||||||
{
|
{
|
||||||
numModules = nMod;
|
numModules = nMod;
|
||||||
|
|
||||||
|
@ -42,8 +44,12 @@ int fader_init(uint32_t nMod)
|
||||||
curColour[i].red = targetColour[i].red = 0;
|
curColour[i].red = targetColour[i].red = 0;
|
||||||
curColour[i].green = targetColour[i].green = 0;
|
curColour[i].green = targetColour[i].green = 0;
|
||||||
curColour[i].blue = targetColour[i].blue = 0;
|
curColour[i].blue = targetColour[i].blue = 0;
|
||||||
|
curColour[i].white = targetColour[i].white = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store LED context (initalized externally)
|
||||||
|
ledCtx = ctx;
|
||||||
|
|
||||||
// timestamp for the first frame
|
// timestamp for the first frame
|
||||||
nextFrame = get_hires_time() + interval;
|
nextFrame = get_hires_time() + interval;
|
||||||
|
|
||||||
|
@ -56,39 +62,37 @@ void fader_shutdown(void)
|
||||||
free(targetColour);
|
free(targetColour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b)
|
void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
|
||||||
{
|
{
|
||||||
curColour[module].red = targetColour[module].red = r;
|
curColour[module].red = targetColour[module].red = r;
|
||||||
curColour[module].green = targetColour[module].green = g;
|
curColour[module].green = targetColour[module].green = g;
|
||||||
curColour[module].blue = targetColour[module].blue = b;
|
curColour[module].blue = targetColour[module].blue = b;
|
||||||
|
curColour[module].white = targetColour[module].white = w;
|
||||||
|
|
||||||
somethingChanged = 1;
|
somethingChanged = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b)
|
void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
|
||||||
{
|
{
|
||||||
targetColour[module].red = r;
|
targetColour[module].red = r;
|
||||||
targetColour[module].green = g;
|
targetColour[module].green = g;
|
||||||
targetColour[module].blue = b;
|
targetColour[module].blue = b;
|
||||||
|
targetColour[module].white = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b)
|
void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
|
||||||
{
|
{
|
||||||
curColour[module].red += r;
|
curColour[module].red += r;
|
||||||
curColour[module].green += g;
|
curColour[module].green += g;
|
||||||
curColour[module].blue += b;
|
curColour[module].blue += b;
|
||||||
|
curColour[module].white += w;
|
||||||
|
|
||||||
if(curColour[module].red > 255) { curColour[module].red = 255; }
|
if(curColour[module].red > 255) { curColour[module].red = 255; }
|
||||||
if(curColour[module].green > 255) { curColour[module].green = 255; }
|
if(curColour[module].green > 255) { curColour[module].green = 255; }
|
||||||
if(curColour[module].blue > 255) { curColour[module].blue = 255; }
|
if(curColour[module].blue > 255) { curColour[module].blue = 255; }
|
||||||
|
if(curColour[module].white > 255) { curColour[module].white = 255; }
|
||||||
|
|
||||||
targetColour[module].red += r;
|
targetColour[module] = curColour[module];
|
||||||
targetColour[module].green += g;
|
|
||||||
targetColour[module].blue += b;
|
|
||||||
|
|
||||||
if(targetColour[module].red > 255) { targetColour[module].red = 255; }
|
|
||||||
if(targetColour[module].green > 255) { targetColour[module].green = 255; }
|
|
||||||
if(targetColour[module].blue > 255) { targetColour[module].blue = 255; }
|
|
||||||
|
|
||||||
somethingChanged = 1;
|
somethingChanged = 1;
|
||||||
}
|
}
|
||||||
|
@ -137,15 +141,17 @@ void fader_update(void)
|
||||||
fade_colour(&(curColour[i].red), &(targetColour[i].red), &somethingChanged);
|
fade_colour(&(curColour[i].red), &(targetColour[i].red), &somethingChanged);
|
||||||
fade_colour(&(curColour[i].green), &(targetColour[i].green), &somethingChanged);
|
fade_colour(&(curColour[i].green), &(targetColour[i].green), &somethingChanged);
|
||||||
fade_colour(&(curColour[i].blue), &(targetColour[i].blue), &somethingChanged);
|
fade_colour(&(curColour[i].blue), &(targetColour[i].blue), &somethingChanged);
|
||||||
|
fade_colour(&(curColour[i].white), &(targetColour[i].white), &somethingChanged);
|
||||||
|
|
||||||
ws2801_set_colour(i,
|
sk6812_set_colour(ledCtx, i,
|
||||||
(uint8_t)curColour[i].red,
|
(uint8_t)curColour[i].red,
|
||||||
(uint8_t)curColour[i].green,
|
(uint8_t)curColour[i].green,
|
||||||
(uint8_t)curColour[i].blue);
|
(uint8_t)curColour[i].blue,
|
||||||
|
(uint8_t)curColour[i].white);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(somethingChanged) {
|
if(somethingChanged) {
|
||||||
ws2801_send_update();
|
sk6812_send_update(ledCtx);
|
||||||
somethingChanged = 0;
|
somethingChanged = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/fader.h
10
src/fader.h
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
int fader_init(uint32_t nMod);
|
struct sk6812_ctx;
|
||||||
|
|
||||||
|
int fader_init(uint32_t nMod, struct sk6812_ctx *ctx);
|
||||||
void fader_shutdown(void);
|
void fader_shutdown(void);
|
||||||
void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b);
|
void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b);
|
void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b);
|
void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
void fader_set_fadestep(uint8_t newFadestep);
|
void fader_set_fadestep(uint8_t newFadestep);
|
||||||
void fader_update(void);
|
void fader_update(void);
|
||||||
void fader_wait_frame(void);
|
void fader_wait_frame(void);
|
||||||
|
|
14
src/main.c
14
src/main.c
|
@ -5,7 +5,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "ws2801.h"
|
#include "sk6812.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "fader.h"
|
#include "fader.h"
|
||||||
#include "udpproto.h"
|
#include "udpproto.h"
|
||||||
|
@ -13,9 +13,13 @@
|
||||||
#define PORT 2703
|
#define PORT 2703
|
||||||
|
|
||||||
#define NUM_MODULES 160
|
#define NUM_MODULES 160
|
||||||
|
#define GPIO_IDX 960
|
||||||
|
#define BASE_ADDR ((void*)0x40000000U)
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
struct sk6812_ctx ctx;
|
||||||
|
|
||||||
// initialize logger
|
// initialize logger
|
||||||
logger_init();
|
logger_init();
|
||||||
|
|
||||||
|
@ -26,13 +30,13 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize ws2801 library
|
// initialize ws2801 library
|
||||||
if(ws2801_init(NUM_MODULES) == -1) {
|
if(sk6812_init(&ctx, GPIO_IDX, BASE_ADDR, NUM_MODULES) == -1) {
|
||||||
LOG(LVL_FATAL, "Could not initialize WS2801 library.");
|
LOG(LVL_FATAL, "Could not initialize SK6812 library.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise the LED fader
|
// initialise the LED fader
|
||||||
if(fader_init(NUM_MODULES) == -1) {
|
if(fader_init(NUM_MODULES, &ctx) == -1) {
|
||||||
LOG(LVL_FATAL, "Could not initialize the LED fader.");
|
LOG(LVL_FATAL, "Could not initialize the LED fader.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +51,7 @@ int main(void)
|
||||||
|
|
||||||
// shut down all modules
|
// shut down all modules
|
||||||
fader_shutdown();
|
fader_shutdown();
|
||||||
ws2801_shutdown();
|
sk6812_shutdown(&ctx);
|
||||||
udpproto_shutdown();
|
udpproto_shutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
45
src/sk6812.c
Normal file
45
src/sk6812.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/spi/spidev.h>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "sk6812.h"
|
||||||
|
|
||||||
|
int sk6812_init(struct sk6812_ctx *ctx, uint32_t gpio_idx, void *phys_baseptr, uint32_t num_modules)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
// - map memory
|
||||||
|
// - setup GPIO
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk6812_shutdown(struct sk6812_ctx *ctx)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
// - unmap memory
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk6812_set_colour(struct sk6812_ctx *ctx, uint32_t module, uint8_t red, uint8_t green, uint8_t blue, uint8_t white)
|
||||||
|
{
|
||||||
|
uint32_t value =
|
||||||
|
((uint32_t)red << 24U) |
|
||||||
|
((uint32_t)green << 16U) |
|
||||||
|
((uint32_t)blue << 8U) |
|
||||||
|
(uint32_t)white;
|
||||||
|
|
||||||
|
ctx->memptr->led_data[module] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk6812_send_update(struct sk6812_ctx *ctx)
|
||||||
|
{
|
||||||
|
// TODO: generate rising edge on GPIO
|
||||||
|
}
|
||||||
|
|
23
src/sk6812.h
Normal file
23
src/sk6812.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef SK6812_H
|
||||||
|
#define SK6812_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct sk6812_memory
|
||||||
|
{
|
||||||
|
uint32_t num_leds;
|
||||||
|
uint32_t led_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sk6812_ctx
|
||||||
|
{
|
||||||
|
struct sk6812_memory *memptr;
|
||||||
|
char *gpio_value_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
int sk6812_init(struct sk6812_ctx *ctx, uint32_t gpio_idx, void *phys_baseptr, uint32_t num_modules);
|
||||||
|
void sk6812_shutdown(struct sk6812_ctx *ctx);
|
||||||
|
void sk6812_set_colour(struct sk6812_ctx *ctx, uint32_t module, uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
|
||||||
|
void sk6812_send_update(struct sk6812_ctx *ctx);
|
||||||
|
|
||||||
|
#endif // SK6812_H
|
|
@ -50,7 +50,7 @@ int udpproto_process(void)
|
||||||
uint8_t pkgbuf[65536];
|
uint8_t pkgbuf[65536];
|
||||||
ssize_t rcvbytes, offset = 0;
|
ssize_t rcvbytes, offset = 0;
|
||||||
|
|
||||||
uint8_t r, g, b, action, module;
|
uint8_t r, g, b, w, action, module;
|
||||||
int fds_ready;
|
int fds_ready;
|
||||||
|
|
||||||
// check if there is data to be read (to prevent blocking)
|
// check if there is data to be read (to prevent blocking)
|
||||||
|
@ -81,25 +81,26 @@ int udpproto_process(void)
|
||||||
|
|
||||||
// parse commands from packet
|
// parse commands from packet
|
||||||
offset = 0;
|
offset = 0;
|
||||||
while(offset <= rcvbytes - 4) {
|
while(offset <= rcvbytes - 5) {
|
||||||
action = pkgbuf[offset + 0];
|
action = pkgbuf[offset + 0];
|
||||||
module = pkgbuf[offset + 1];
|
module = pkgbuf[offset + 1];
|
||||||
r = pkgbuf[offset + 2];
|
r = pkgbuf[offset + 2];
|
||||||
g = pkgbuf[offset + 3];
|
g = pkgbuf[offset + 3];
|
||||||
b = pkgbuf[offset + 4];
|
b = pkgbuf[offset + 4];
|
||||||
|
w = pkgbuf[offset + 5];
|
||||||
offset += 5;
|
offset += 5;
|
||||||
|
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case SET_COLOUR:
|
case SET_COLOUR:
|
||||||
fader_set_colour(module, r, g, b);
|
fader_set_colour(module, r, g, b, w);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FADE_COLOUR:
|
case FADE_COLOUR:
|
||||||
fader_fade_colour(module, r, g, b);
|
fader_fade_colour(module, r, g, b, w);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADD_COLOUR:
|
case ADD_COLOUR:
|
||||||
fader_add_colour(module, r, g, b);
|
fader_add_colour(module, r, g, b, w);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_FADESTEP:
|
case SET_FADESTEP:
|
||||||
|
@ -111,7 +112,7 @@ int udpproto_process(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rcvbytes / 5; // number of commands in packet
|
return rcvbytes / 6; // number of commands in packet
|
||||||
}
|
}
|
||||||
|
|
||||||
void udpproto_shutdown(void)
|
void udpproto_shutdown(void)
|
||||||
|
|
107
src/ws2801.c
107
src/ws2801.c
|
@ -1,107 +0,0 @@
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <linux/spi/spidev.h>
|
|
||||||
|
|
||||||
//#include <wiringPi.h>
|
|
||||||
|
|
||||||
#include "logger.h"
|
|
||||||
#include "ws2801.h"
|
|
||||||
|
|
||||||
static const char *spi_dev = "/dev/spidev0.0";
|
|
||||||
static const uint32_t spi_speed = 1000000; // clock freq in Hz
|
|
||||||
static const uint16_t spi_delay = 0; // us
|
|
||||||
static const uint8_t spi_bits = 8; // bits per word
|
|
||||||
|
|
||||||
uint32_t numModules;
|
|
||||||
uint8_t *message;
|
|
||||||
|
|
||||||
int spi_fd = 0;
|
|
||||||
|
|
||||||
void send_message(void)
|
|
||||||
{
|
|
||||||
struct spi_ioc_transfer tr = {
|
|
||||||
.tx_buf = (unsigned long)message,
|
|
||||||
.rx_buf = (unsigned long)NULL,
|
|
||||||
.len = 3 * numModules,
|
|
||||||
.delay_usecs = spi_delay,
|
|
||||||
.speed_hz = spi_speed,
|
|
||||||
.bits_per_word = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
if(ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr) < 0) {
|
|
||||||
LOG(LVL_ERR, "ws2801: could not send SPI message: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ws2801_init(uint32_t nMod)
|
|
||||||
{
|
|
||||||
// Initialize SPI
|
|
||||||
// We need to have stable data at falling edge of the spi interface (this
|
|
||||||
// means rising edge at the led strip, as the signal is inverted.
|
|
||||||
uint8_t spi_mode = SPI_NO_CS; // | SPI_CPOL;
|
|
||||||
|
|
||||||
spi_fd = open(spi_dev, O_RDWR);
|
|
||||||
if(spi_fd < 0) {
|
|
||||||
LOG(LVL_ERR, "ws2801: cannot open %s: %s", spi_dev, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode) == -1) {
|
|
||||||
LOG(LVL_ERR, "ws2801: cannot change SPI mode: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits) == -1) {
|
|
||||||
LOG(LVL_ERR, "ws2801: cannot change SPI bits per word: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) == -1) {
|
|
||||||
LOG(LVL_ERR, "ws2801: cannot change SPI speed: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the message array
|
|
||||||
numModules = nMod;
|
|
||||||
message = malloc(3 * nMod * sizeof(uint8_t));
|
|
||||||
|
|
||||||
if(!message) {
|
|
||||||
LOG(LVL_ERR, "ws2801: could not allocate the message array!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ws2801_shutdown(void)
|
|
||||||
{
|
|
||||||
close(spi_fd);
|
|
||||||
|
|
||||||
if(message != NULL) { free(message); message = NULL; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void ws2801_set_colour(uint32_t module, uint8_t red, uint8_t green, uint8_t blue)
|
|
||||||
{
|
|
||||||
//message[3*module + 0] = ~red;
|
|
||||||
//message[3*module + 1] = ~green;
|
|
||||||
//message[3*module + 2] = ~blue;
|
|
||||||
message[3*module + 0] = red;
|
|
||||||
message[3*module + 1] = blue;
|
|
||||||
message[3*module + 2] = green;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ws2801_send_update(void)
|
|
||||||
{
|
|
||||||
send_message();
|
|
||||||
|
|
||||||
static const struct timespec sleepval = {0, 550000};
|
|
||||||
nanosleep(&sleepval, NULL);
|
|
||||||
}
|
|
||||||
|
|
11
src/ws2801.h
11
src/ws2801.h
|
@ -1,11 +0,0 @@
|
||||||
#ifndef WS2801_H
|
|
||||||
#define WS2801_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int ws2801_init(uint32_t num_modules);
|
|
||||||
void ws2801_shutdown(void);
|
|
||||||
void ws2801_set_colour(uint32_t module, uint8_t red, uint8_t green, uint8_t blue);
|
|
||||||
void ws2801_send_update(void);
|
|
||||||
|
|
||||||
#endif // WS2801_H
|
|
Loading…
Reference in a new issue