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
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

View File

@ -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)
{

View File

@ -5,6 +5,7 @@
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.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)
{
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;
}

View File

@ -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

View File

@ -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)