Finalize sk6812 control via memory interface

This commit is contained in:
Thomas Kolb 2018-06-17 19:28:36 +02:00
parent ead78ab1ce
commit 8790cf6a5e
5 changed files with 79 additions and 18 deletions

View file

@ -13,7 +13,7 @@ double nextFrame;
int somethingChanged = 0; // indicates when a sk6812 update is required 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 { struct Colour {
float red, green, blue, white; // value range is 0.0 to 255.0 float red, green, blue, white; // value range is 0.0 to 255.0

View file

@ -12,9 +12,9 @@
#define PORT 2703 #define PORT 2703
#define NUM_MODULES 160 #define NUM_MODULES 300
#define GPIO_IDX 960 #define GPIO_IDX 961
#define BASE_ADDR ((void*)0x40000000U) #define BASE_ADDR ((void*)0x40010000U)
int main(void) int main(void)
{ {

View file

@ -5,6 +5,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -13,6 +14,8 @@
int sk6812_init(struct sk6812_ctx *ctx, uint32_t gpio_idx, void *phys_baseptr, uint32_t num_modules) 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. * 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 // write number of modules to mapped memory
ctx->memptr->num_leds = num_modules; 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; 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) 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 value =
((uint32_t)red << 24U) | ((uint32_t)green << 24U) |
((uint32_t)green << 16U) | ((uint32_t)red << 16U) |
((uint32_t)blue << 8U) | ((uint32_t)blue << 8U) |
(uint32_t)white; (uint32_t)white;
ctx->memptr->led_data[module] = value; 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;
} }

View file

@ -15,11 +15,12 @@ struct sk6812_ctx
char *gpio_value_path; char *gpio_value_path;
int devmem_fd; int devmem_fd;
size_t mapped_size; 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); 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_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_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 #endif // SK6812_H

View file

@ -17,6 +17,8 @@
#define ADD_COLOUR 2 #define ADD_COLOUR 2
#define SET_FADESTEP 3 #define SET_FADESTEP 3
#define BYTES_PER_PACKET 7
int sock; int sock;
int udpproto_init(uint16_t port) int udpproto_init(uint16_t port)
@ -50,7 +52,8 @@ 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, w, action, module; uint8_t r, g, b, w, action;
uint16_t 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,14 +84,15 @@ int udpproto_process(void)
// parse commands from packet // parse commands from packet
offset = 0; offset = 0;
while(offset <= rcvbytes - 5) { while(offset <= rcvbytes - BYTES_PER_PACKET) {
action = pkgbuf[offset + 0]; action = pkgbuf[offset + 0];
module = pkgbuf[offset + 1]; module = (uint16_t)pkgbuf[offset + 1] << 8;
r = pkgbuf[offset + 2]; module |= pkgbuf[offset + 2];
g = pkgbuf[offset + 3]; r = pkgbuf[offset + 3];
b = pkgbuf[offset + 4]; g = pkgbuf[offset + 4];
w = pkgbuf[offset + 5]; b = pkgbuf[offset + 5];
offset += 5; w = pkgbuf[offset + 6];
offset += BYTES_PER_PACKET;
switch(action) { switch(action) {
case SET_COLOUR: 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) void udpproto_shutdown(void)