From 8790cf6a5eb1cd1e6968833be1455cde01886670 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sun, 17 Jun 2018 19:28:36 +0200 Subject: [PATCH] Finalize sk6812 control via memory interface --- src/fader.c | 2 +- src/main.c | 6 ++--- src/sk6812.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++---- src/sk6812.h | 3 ++- src/udpproto.c | 22 ++++++++++------- 5 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/fader.c b/src/fader.c index 40dee4b..e488520 100644 --- a/src/fader.c +++ b/src/fader.c @@ -13,7 +13,7 @@ double nextFrame; int somethingChanged = 0; // indicates when a sk6812 update is required -static const double interval = 0.01f; +static const double interval = 1.0f / 75.0f; struct Colour { float red, green, blue, white; // value range is 0.0 to 255.0 diff --git a/src/main.c b/src/main.c index 7bf13e9..c0b2325 100644 --- a/src/main.c +++ b/src/main.c @@ -12,9 +12,9 @@ #define PORT 2703 -#define NUM_MODULES 160 -#define GPIO_IDX 960 -#define BASE_ADDR ((void*)0x40000000U) +#define NUM_MODULES 300 +#define GPIO_IDX 961 +#define BASE_ADDR ((void*)0x40010000U) int main(void) { diff --git a/src/sk6812.c b/src/sk6812.c index f5af1f8..298714a 100644 --- a/src/sk6812.c +++ b/src/sk6812.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -13,6 +14,8 @@ int sk6812_init(struct sk6812_ctx *ctx, uint32_t gpio_idx, void *phys_baseptr, uint32_t num_modules) { + ctx->gpio_idx = gpio_idx; + /* * Setup memory map for LED memory. */ @@ -41,6 +44,34 @@ int sk6812_init(struct sk6812_ctx *ctx, uint32_t gpio_idx, void *phys_baseptr, u // write number of modules to mapped memory ctx->memptr->num_leds = num_modules; + /* + * set up GPIO + */ + char filename[256]; + char data[32]; + int dlen; + + int fd = open("/sys/class/gpio/export", O_WRONLY); + if(ctx->devmem_fd == -1) { + LOG(LVL_ERR, "sk6812: open(/sys/class/gpio/export, WRONLY) failed: %s.", strerror(errno)); + return -1; + } + + dlen = snprintf(data, 32, "%d\n", ctx->gpio_idx); + write(fd, data, dlen); + close(fd); + + snprintf(filename, 256, "/sys/class/gpio/gpio%u/direction", ctx->gpio_idx); + + fd = open(filename, O_WRONLY); + if(ctx->devmem_fd == -1) { + LOG(LVL_ERR, "sk6812: open(%s, WRONLY) failed: %s.", filename, strerror(errno)); + return -1; + } + + write(fd, "out\n", 4); + close(fd); + return 0; } @@ -52,17 +83,42 @@ 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) { + // despite the info in the datasheet, red and green are swapped :/ uint32_t value = - ((uint32_t)red << 24U) | - ((uint32_t)green << 16U) | + ((uint32_t)green << 24U) | + ((uint32_t)red << 16U) | ((uint32_t)blue << 8U) | (uint32_t)white; ctx->memptr->led_data[module] = value; } -void sk6812_send_update(struct sk6812_ctx *ctx) +int sk6812_send_update(struct sk6812_ctx *ctx) { - // TODO: generate rising edge on GPIO + LOG(LVL_DEBUG, "Updating with LED count: %u", ctx->memptr->num_leds); + + char filename[256]; + + snprintf(filename, 256, "/sys/class/gpio/gpio%u/value", ctx->gpio_idx); + + int fd = open(filename, O_WRONLY); + if(ctx->devmem_fd == -1) { + LOG(LVL_ERR, "sk6812: open(%s, WRONLY) failed: %s.", filename, strerror(errno)); + return -1; + } + + write(fd, "0\n", 2); + close(fd); + + fd = open(filename, O_WRONLY); + if(ctx->devmem_fd == -1) { + LOG(LVL_ERR, "sk6812: open(%s, WRONLY) failed: %s.", filename, strerror(errno)); + return -1; + } + + write(fd, "1\n", 2); + close(fd); + + return 0; } diff --git a/src/sk6812.h b/src/sk6812.h index 77b19b8..00ffee5 100644 --- a/src/sk6812.h +++ b/src/sk6812.h @@ -15,11 +15,12 @@ struct sk6812_ctx char *gpio_value_path; int devmem_fd; size_t mapped_size; + uint32_t gpio_idx; }; 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); +int sk6812_send_update(struct sk6812_ctx *ctx); #endif // SK6812_H diff --git a/src/udpproto.c b/src/udpproto.c index 02fd911..fd5076c 100644 --- a/src/udpproto.c +++ b/src/udpproto.c @@ -17,6 +17,8 @@ #define ADD_COLOUR 2 #define SET_FADESTEP 3 +#define BYTES_PER_PACKET 7 + int sock; int udpproto_init(uint16_t port) @@ -50,7 +52,8 @@ int udpproto_process(void) uint8_t pkgbuf[65536]; ssize_t rcvbytes, offset = 0; - uint8_t r, g, b, w, action, module; + uint8_t r, g, b, w, action; + uint16_t module; int fds_ready; // check if there is data to be read (to prevent blocking) @@ -81,14 +84,15 @@ int udpproto_process(void) // parse commands from packet offset = 0; - while(offset <= rcvbytes - 5) { + while(offset <= rcvbytes - BYTES_PER_PACKET) { 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; + module = (uint16_t)pkgbuf[offset + 1] << 8; + module |= pkgbuf[offset + 2]; + r = pkgbuf[offset + 3]; + g = pkgbuf[offset + 4]; + b = pkgbuf[offset + 5]; + w = pkgbuf[offset + 6]; + offset += BYTES_PER_PACKET; switch(action) { case SET_COLOUR: @@ -112,7 +116,7 @@ int udpproto_process(void) } } - return rcvbytes / 6; // number of commands in packet + return rcvbytes / BYTES_PER_PACKET; // number of commands in packet } void udpproto_shutdown(void)