#include #include #include #include #include #include #include #include #include #include "logger.h" #include "sk6812.h" 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. */ size_t mapsize = num_modules*sizeof(uint32_t); size_t pagesize = (size_t)getpagesize(); if((mapsize % pagesize) != 0) { mapsize = pagesize * (mapsize / pagesize + 1); } ctx->devmem_fd = open("/dev/mem", O_RDWR|O_SYNC); if(ctx->devmem_fd == -1) { LOG(LVL_ERR, "sk6812: open(/dev/mem) failed: %s.", strerror(errno)); return -1; } ctx->memptr = (struct sk6812_memory*)mmap(0, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, ctx->devmem_fd, (off_t)phys_baseptr); if(ctx->memptr == MAP_FAILED) { LOG(LVL_ERR, "sk6812: mmap(0x%08X) failed: %s.", phys_baseptr, strerror(errno)); close(ctx->devmem_fd); return -1; } ctx->mapped_size = mapsize; // 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; } void sk6812_shutdown(struct sk6812_ctx *ctx) { munmap(ctx->memptr, ctx->mapped_size); close(ctx->devmem_fd); } 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)green << 24U) | ((uint32_t)red << 16U) | ((uint32_t)blue << 8U) | (uint32_t)white; ctx->memptr->led_data[module] = value; } int sk6812_send_update(struct sk6812_ctx *ctx) { 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; }