From bca64a858ab672873be9398079a446ece3639da9 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Wed, 13 Jun 2018 23:06:45 +0200 Subject: [PATCH] Refactored to sk6812; Added white channel --- CMakeLists.txt | 4 +- src/fader.c | 40 ++++++++++-------- src/fader.h | 10 +++-- src/main.c | 14 ++++--- src/sk6812.c | 45 +++++++++++++++++++++ src/sk6812.h | 23 +++++++++++ src/udpproto.c | 13 +++--- src/ws2801.c | 107 ------------------------------------------------- src/ws2801.h | 11 ----- 9 files changed, 115 insertions(+), 152 deletions(-) create mode 100644 src/sk6812.c create mode 100644 src/sk6812.h delete mode 100644 src/ws2801.c delete mode 100644 src/ws2801.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c78a03d..9f1b8ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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( diff --git a/src/fader.c b/src/fader.c index f68099d..40dee4b 100644 --- a/src/fader.c +++ b/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; } } diff --git a/src/fader.h b/src/fader.h index f729161..e378f75 100644 --- a/src/fader.h +++ b/src/fader.h @@ -3,11 +3,13 @@ #include -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); diff --git a/src/main.c b/src/main.c index 1deffa6..7bf13e9 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ #include #include -#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; diff --git a/src/sk6812.c b/src/sk6812.c new file mode 100644 index 0000000..4f7693c --- /dev/null +++ b/src/sk6812.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 +} + diff --git a/src/sk6812.h b/src/sk6812.h new file mode 100644 index 0000000..c2e01af --- /dev/null +++ b/src/sk6812.h @@ -0,0 +1,23 @@ +#ifndef SK6812_H +#define SK6812_H + +#include + +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 diff --git a/src/udpproto.c b/src/udpproto.c index 0899b50..02fd911 100644 --- a/src/udpproto.c +++ b/src/udpproto.c @@ -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) diff --git a/src/ws2801.c b/src/ws2801.c deleted file mode 100644 index 89ac550..0000000 --- a/src/ws2801.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -//#include - -#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); -} - diff --git a/src/ws2801.h b/src/ws2801.h deleted file mode 100644 index 3791842..0000000 --- a/src/ws2801.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef WS2801_H -#define WS2801_H - -#include - -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