Finalize sk6812 control via memory interface
This commit is contained in:
parent
ead78ab1ce
commit
8790cf6a5e
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
64
src/sk6812.c
64
src/sk6812.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue