From 8bc5d05ec10763190cba9b2aff19b7a6a4b6d5ba Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Mon, 30 Jul 2018 22:56:18 +0200 Subject: [PATCH] First steps towards RaspberryPi hat support - Allow to have multiple faders/strips - Added strip ID to UDP protocol --- src/fader.c | 146 ++++++++++++++++++++----------------------------- src/fader.h | 32 ++++++++--- src/main.c | 34 ++++++++---- src/udpproto.c | 40 +++++++++----- src/udpproto.h | 4 +- 5 files changed, 136 insertions(+), 120 deletions(-) diff --git a/src/fader.c b/src/fader.c index e488520..6723aec 100644 --- a/src/fader.c +++ b/src/fader.c @@ -6,102 +6,80 @@ #include "fader.h" -uint32_t numModules; - -float fadestep = 1; -double nextFrame; - -int somethingChanged = 0; // indicates when a sk6812 update is required - -static const double interval = 1.0f / 75.0f; - -struct Colour { - float red, green, blue, white; // value range is 0.0 to 255.0 -}; - -struct Colour *curColour; -struct Colour *targetColour; - -struct sk6812_ctx *ledCtx; // global context for the one strip we control - -int fader_init(uint32_t nMod, struct sk6812_ctx *ctx) +int fader_init(struct fader_ctx *ctx, uint32_t nMod, struct sk6812_ctx *ledCtx) { - numModules = nMod; + ctx->num_modules = nMod; + ctx->fadestep = 1; - curColour = malloc(nMod * sizeof(struct Colour)); - if(!curColour) { + ctx->cur_colour = malloc(nMod * sizeof(struct fader_colour)); + if(!ctx->cur_colour) { LOG(LVL_ERR, "fader: could not allocate the array of current colours!"); return -1; } - targetColour = malloc(nMod * sizeof(struct Colour)); - if(!targetColour) { + ctx->target_colour = malloc(nMod * sizeof(struct fader_colour)); + if(!ctx->target_colour) { LOG(LVL_ERR, "fader: could not allocate the array of target colours!"); return -1; } - for(uint32_t i = 0; i < numModules; i++) { - 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; + for(uint32_t i = 0; i < ctx->num_modules; i++) { + ctx->cur_colour[i].red = ctx->target_colour[i].red = 0; + ctx->cur_colour[i].green = ctx->target_colour[i].green = 0; + ctx->cur_colour[i].blue = ctx->target_colour[i].blue = 0; + ctx->cur_colour[i].white = ctx->target_colour[i].white = 0; } // store LED context (initalized externally) - ledCtx = ctx; - - // timestamp for the first frame - nextFrame = get_hires_time() + interval; + ctx->led_ctx = ledCtx; return 0; } -void fader_shutdown(void) +void fader_shutdown(struct fader_ctx *ctx) { - free(curColour); - free(targetColour); + free(ctx->cur_colour); + free(ctx->target_colour); } -void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) +void fader_set_colour(struct fader_ctx *ctx, 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; + ctx->cur_colour[module].red = ctx->target_colour[module].red = r; + ctx->cur_colour[module].green = ctx->target_colour[module].green = g; + ctx->cur_colour[module].blue = ctx->target_colour[module].blue = b; + ctx->cur_colour[module].white = ctx->target_colour[module].white = w; - somethingChanged = 1; + ctx->something_changed = 1; } -void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) +void fader_fade_colour(struct fader_ctx *ctx, 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; + ctx->target_colour[module].red = r; + ctx->target_colour[module].green = g; + ctx->target_colour[module].blue = b; + ctx->target_colour[module].white = w; } -void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) +void fader_add_colour(struct fader_ctx *ctx, 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; + ctx->cur_colour[module].red += r; + ctx->cur_colour[module].green += g; + ctx->cur_colour[module].blue += b; + ctx->cur_colour[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; } + if(ctx->cur_colour[module].red > 255) { ctx->cur_colour[module].red = 255; } + if(ctx->cur_colour[module].green > 255) { ctx->cur_colour[module].green = 255; } + if(ctx->cur_colour[module].blue > 255) { ctx->cur_colour[module].blue = 255; } + if(ctx->cur_colour[module].white > 255) { ctx->cur_colour[module].white = 255; } - targetColour[module] = curColour[module]; + ctx->target_colour[module] = ctx->cur_colour[module]; - somethingChanged = 1; + ctx->something_changed = 1; } -void fader_set_fadestep(uint8_t newFadestep) +void fader_set_fadestep(struct fader_ctx *ctx, uint8_t newFadestep) { - // The original avr implementition had a frame rate of 25fps (interval 0,04 sec.). - // This scales the fadestep to the current frame rate. - fadestep = (float)newFadestep * interval / 0.04f; + ctx->fadestep = newFadestep; } /*! @@ -111,53 +89,47 @@ void fader_set_fadestep(uint8_t newFadestep) * \param target The target value that should be reached. * \param changed Output value which is set to 1 if cur was changed. */ -void fade_colour(float *cur, const float *target, int *changed) +void fade_colour(struct fader_ctx *ctx, float *cur, const float *target, int *changed) { float diff; if(*cur > *target) { diff = *cur - *target; - if(diff < fadestep) { + if(diff < ctx->fadestep) { *cur = *target; } else { - *cur -= fadestep; + *cur -= ctx->fadestep; } *changed = 1; } else if(*cur < *target) { diff = *target - *cur; - if(diff < fadestep) { + if(diff < ctx->fadestep) { *cur = *target; } else { - *cur += fadestep; + *cur += ctx->fadestep; } *changed = 1; } } -void fader_update(void) +void fader_update(struct fader_ctx *ctx) { - for(uint32_t i = 0; i < numModules; i++) { - 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); + for(uint32_t i = 0; i < ctx->num_modules; i++) { + fade_colour(ctx, &(ctx->cur_colour[i].red), &(ctx->target_colour[i].red), &ctx->something_changed); + fade_colour(ctx, &(ctx->cur_colour[i].green), &(ctx->target_colour[i].green), &ctx->something_changed); + fade_colour(ctx, &(ctx->cur_colour[i].blue), &(ctx->target_colour[i].blue), &ctx->something_changed); + fade_colour(ctx, &(ctx->cur_colour[i].white), &(ctx->target_colour[i].white), &ctx->something_changed); - sk6812_set_colour(ledCtx, i, - (uint8_t)curColour[i].red, - (uint8_t)curColour[i].green, - (uint8_t)curColour[i].blue, - (uint8_t)curColour[i].white); + sk6812_set_colour(ctx->led_ctx, i, + (uint8_t)ctx->cur_colour[i].red, + (uint8_t)ctx->cur_colour[i].green, + (uint8_t)ctx->cur_colour[i].blue, + (uint8_t)ctx->cur_colour[i].white); } - if(somethingChanged) { - sk6812_send_update(ledCtx); - somethingChanged = 0; + if(ctx->something_changed) { + sk6812_send_update(ctx->led_ctx); + ctx->something_changed = 0; } } - -void fader_wait_frame(void) -{ - sleep_until(nextFrame); - nextFrame += interval; -} diff --git a/src/fader.h b/src/fader.h index e378f75..ca3c50e 100644 --- a/src/fader.h +++ b/src/fader.h @@ -5,13 +5,29 @@ 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, 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); +struct fader_colour { + float red, green, blue, white; // value range is 0.0 to 255.0 +}; + +struct fader_ctx { + uint32_t num_modules; + + struct fader_colour *cur_colour; + struct fader_colour *target_colour; + + struct sk6812_ctx *led_ctx; + + uint8_t something_changed; + + float fadestep; +}; + +int fader_init(struct fader_ctx *ctx, uint32_t nMod, struct sk6812_ctx *ledCtx); +void fader_shutdown(struct fader_ctx *ctx); +void fader_set_colour(struct fader_ctx *ctx, uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w); +void fader_fade_colour(struct fader_ctx *ctx, uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w); +void fader_add_colour(struct fader_ctx *ctx, uint32_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w); +void fader_set_fadestep(struct fader_ctx *ctx, uint8_t newFadestep); +void fader_update(struct fader_ctx *ctx); #endif // FADER_H diff --git a/src/main.c b/src/main.c index 827ddd3..f50070b 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ #include "logger.h" #include "fader.h" #include "udpproto.h" +#include "utils.h" #define PORT 2703 @@ -18,6 +19,8 @@ #define GPIO_IDX 960 #define BASE_ADDR ((void*)0x40000000U) +#define INTERVAL 0.01 + struct CmdLineArgs { uint16_t port; void *base_addr; @@ -25,6 +28,12 @@ struct CmdLineArgs { uint32_t num_modules; }; +void wait_frame(double *nextFrame, double interval) +{ + sleep_until(*nextFrame); + *nextFrame += interval; +} + int parse_args(int argc, char **argv, struct CmdLineArgs *args) { int opt; @@ -67,9 +76,12 @@ int parse_args(int argc, char **argv, struct CmdLineArgs *args) int main(int argc, char **argv) { struct sk6812_ctx ctx; + struct fader_ctx fader_ctx; struct CmdLineArgs args; + double nextFrame = get_hires_time() + INTERVAL; + // initialize logger logger_init(); @@ -86,12 +98,6 @@ int main(int argc, char **argv) return 1; } - // initialise the UDP server - if(udpproto_init(PORT) == -1) { - LOG(LVL_FATAL, "Could not initialize the UDP server."); - return 1; - } - // initialize ws2801 library if(sk6812_init(&ctx, GPIO_IDX, BASE_ADDR, NUM_MODULES) == -1) { LOG(LVL_FATAL, "Could not initialize SK6812 library."); @@ -99,23 +105,29 @@ int main(int argc, char **argv) } // initialise the LED fader - if(fader_init(NUM_MODULES, &ctx) == -1) { + if(fader_init(&fader_ctx, NUM_MODULES, &ctx) == -1) { LOG(LVL_FATAL, "Could not initialize the LED fader."); return 1; } + // initialise the UDP server + if(udpproto_init(PORT, &fader_ctx, 1) == -1) { + LOG(LVL_FATAL, "Could not initialize the UDP server."); + return 1; + } + LOG(LVL_INFO, "Initialisation complete."); while(1) { udpproto_process(); - fader_update(); - fader_wait_frame(); + fader_update(&fader_ctx); + wait_frame(&nextFrame, INTERVAL); } // shut down all modules - fader_shutdown(); - sk6812_shutdown(&ctx); udpproto_shutdown(); + fader_shutdown(&fader_ctx); + sk6812_shutdown(&ctx); return 0; } diff --git a/src/udpproto.c b/src/udpproto.c index fd5076c..fc3624b 100644 --- a/src/udpproto.c +++ b/src/udpproto.c @@ -17,14 +17,19 @@ #define ADD_COLOUR 2 #define SET_FADESTEP 3 -#define BYTES_PER_PACKET 7 +#define BYTES_PER_PACKET 8 int sock; +struct fader_ctx *udpproto_faders; +uint32_t udpproto_nstrips; -int udpproto_init(uint16_t port) +int udpproto_init(uint16_t port, struct fader_ctx *faders, uint32_t nstrips) { struct sockaddr_in listen_addr; + udpproto_nstrips = nstrips; + udpproto_faders = faders; + // initialize UDP server socket sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sock == -1) { @@ -52,10 +57,12 @@ int udpproto_process(void) uint8_t pkgbuf[65536]; ssize_t rcvbytes, offset = 0; - uint8_t r, g, b, w, action; + uint8_t r, g, b, w, action, strip; uint16_t module; int fds_ready; + struct fader_ctx *fader; + // check if there is data to be read (to prevent blocking) struct pollfd pfd = { .fd = sock, @@ -86,29 +93,36 @@ int udpproto_process(void) offset = 0; while(offset <= rcvbytes - BYTES_PER_PACKET) { action = pkgbuf[offset + 0]; - 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]; + strip = pkgbuf[offset + 1]; + module = (uint16_t)pkgbuf[offset + 2] << 8; + module |= pkgbuf[offset + 3]; + r = pkgbuf[offset + 4]; + g = pkgbuf[offset + 5]; + b = pkgbuf[offset + 6]; + w = pkgbuf[offset + 7]; offset += BYTES_PER_PACKET; + if(strip > udpproto_nstrips) { + continue; + } + + fader = udpproto_faders + strip; + switch(action) { case SET_COLOUR: - fader_set_colour(module, r, g, b, w); + fader_set_colour(fader, module, r, g, b, w); break; case FADE_COLOUR: - fader_fade_colour(module, r, g, b, w); + fader_fade_colour(fader, module, r, g, b, w); break; case ADD_COLOUR: - fader_add_colour(module, r, g, b, w); + fader_add_colour(fader, module, r, g, b, w); break; case SET_FADESTEP: - fader_set_fadestep(r); // red channel contains the fadestep in this case + fader_set_fadestep(fader, r); // red channel contains the fadestep in this case break; default: diff --git a/src/udpproto.h b/src/udpproto.h index 3f296a8..46bb2e9 100644 --- a/src/udpproto.h +++ b/src/udpproto.h @@ -3,7 +3,9 @@ #include -int udpproto_init(uint16_t port); +struct fader_ctx; + +int udpproto_init(uint16_t port, struct fader_ctx *faders, uint32_t nstrips); int udpproto_process(void); void udpproto_shutdown(void);