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/udpproto.c
|
||||
src/utils.c
|
||||
src/ws2801.c
|
||||
src/sk6812.c
|
||||
src/fader.h
|
||||
src/logger.h
|
||||
src/udpproto.h
|
||||
src/utils.h
|
||||
src/ws2801.h
|
||||
src/sk6812.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
|
40
src/fader.c
40
src/fader.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "logger.h"
|
||||
#include "utils.h"
|
||||
#include "ws2801.h"
|
||||
#include "sk6812.h"
|
||||
|
||||
#include "fader.h"
|
||||
|
||||
|
@ -11,18 +11,20 @@ uint32_t numModules;
|
|||
float fadestep = 1;
|
||||
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;
|
||||
|
||||
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 *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;
|
||||
|
||||
|
@ -42,8 +44,12 @@ int fader_init(uint32_t nMod)
|
|||
curColour[i].red = targetColour[i].red = 0;
|
||||
curColour[i].green = targetColour[i].green = 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
|
||||
nextFrame = get_hires_time() + interval;
|
||||
|
||||
|
@ -56,39 +62,37 @@ void fader_shutdown(void)
|
|||
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].green = targetColour[module].green = g;
|
||||
curColour[module].blue = targetColour[module].blue = b;
|
||||
curColour[module].white = targetColour[module].white = w;
|
||||
|
||||
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].green = g;
|
||||
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].green += g;
|
||||
curColour[module].blue += b;
|
||||
curColour[module].white += w;
|
||||
|
||||
if(curColour[module].red > 255) { curColour[module].red = 255; }
|
||||
if(curColour[module].green > 255) { curColour[module].green = 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].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; }
|
||||
targetColour[module] = curColour[module];
|
||||
|
||||
somethingChanged = 1;
|
||||
}
|
||||
|
@ -137,15 +141,17 @@ void fader_update(void)
|
|||
fade_colour(&(curColour[i].red), &(targetColour[i].red), &somethingChanged);
|
||||
fade_colour(&(curColour[i].green), &(targetColour[i].green), &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].green,
|
||||
(uint8_t)curColour[i].blue);
|
||||
(uint8_t)curColour[i].blue,
|
||||
(uint8_t)curColour[i].white);
|
||||
}
|
||||
|
||||
if(somethingChanged) {
|
||||
ws2801_send_update();
|
||||
sk6812_send_update(ledCtx);
|
||||
somethingChanged = 0;
|
||||
}
|
||||
}
|
||||
|
|
10
src/fader.h
10
src/fader.h
|
@ -3,11 +3,13 @@
|
|||
|
||||
#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_set_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);
|
||||
void fader_add_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, uint8_t w);
|
||||
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_update(void);
|
||||
void fader_wait_frame(void);
|
||||
|
|
14
src/main.c
14
src/main.c
|
@ -5,7 +5,7 @@
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ws2801.h"
|
||||
#include "sk6812.h"
|
||||
#include "logger.h"
|
||||
#include "fader.h"
|
||||
#include "udpproto.h"
|
||||
|
@ -13,9 +13,13 @@
|
|||
#define PORT 2703
|
||||
|
||||
#define NUM_MODULES 160
|
||||
#define GPIO_IDX 960
|
||||
#define BASE_ADDR ((void*)0x40000000U)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sk6812_ctx ctx;
|
||||
|
||||
// initialize logger
|
||||
logger_init();
|
||||
|
||||
|
@ -26,13 +30,13 @@ int main(void)
|
|||
}
|
||||
|
||||
// initialize ws2801 library
|
||||
if(ws2801_init(NUM_MODULES) == -1) {
|
||||
LOG(LVL_FATAL, "Could not initialize WS2801 library.");
|
||||
if(sk6812_init(&ctx, GPIO_IDX, BASE_ADDR, NUM_MODULES) == -1) {
|
||||
LOG(LVL_FATAL, "Could not initialize SK6812 library.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 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.");
|
||||
return 1;
|
||||
}
|
||||
|
@ -47,7 +51,7 @@ int main(void)
|
|||
|
||||
// shut down all modules
|
||||
fader_shutdown();
|
||||
ws2801_shutdown();
|
||||
sk6812_shutdown(&ctx);
|
||||
udpproto_shutdown();
|
||||
|
||||
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];
|
||||
ssize_t rcvbytes, offset = 0;
|
||||
|
||||
uint8_t r, g, b, action, module;
|
||||
uint8_t r, g, b, w, action, module;
|
||||
int fds_ready;
|
||||
|
||||
// check if there is data to be read (to prevent blocking)
|
||||
|
@ -81,25 +81,26 @@ int udpproto_process(void)
|
|||
|
||||
// parse commands from packet
|
||||
offset = 0;
|
||||
while(offset <= rcvbytes - 4) {
|
||||
while(offset <= rcvbytes - 5) {
|
||||
action = pkgbuf[offset + 0];
|
||||
module = pkgbuf[offset + 1];
|
||||
r = pkgbuf[offset + 2];
|
||||
g = pkgbuf[offset + 3];
|
||||
b = pkgbuf[offset + 4];
|
||||
w = pkgbuf[offset + 5];
|
||||
offset += 5;
|
||||
|
||||
switch(action) {
|
||||
case SET_COLOUR:
|
||||
fader_set_colour(module, r, g, b);
|
||||
fader_set_colour(module, r, g, b, w);
|
||||
break;
|
||||
|
||||
case FADE_COLOUR:
|
||||
fader_fade_colour(module, r, g, b);
|
||||
fader_fade_colour(module, r, g, b, w);
|
||||
break;
|
||||
|
||||
case ADD_COLOUR:
|
||||
fader_add_colour(module, r, g, b);
|
||||
fader_add_colour(module, r, g, b, w);
|
||||
break;
|
||||
|
||||
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)
|
||||
|
|
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