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
|
||||
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
64
src/sk6812.c
64
src/sk6812.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue