From eb36cf8e5f13086c73a0a581805dc4977a252e39 Mon Sep 17 00:00:00 2001 From: Daniel Willmann <daniel@totalueberwachung.de> Date: Thu, 1 May 2014 10:04:59 +0200 Subject: [PATCH] Copy over files from ledctrl --- Makefile.am | 18 +----- configure.ac | 7 ++- src/Makefile.am | 23 +++++++ src/mensactrl.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ src/mensaserv.c | 112 ++++++++++++++++++++++++++++++++++ 5 files changed, 296 insertions(+), 19 deletions(-) create mode 100644 src/Makefile.am create mode 100644 src/mensactrl.c create mode 100644 src/mensaserv.c diff --git a/Makefile.am b/Makefile.am index 3a93947..6981c66 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,3 @@ -bin_PROGRAMS = \ - mensa-control - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include -# $(some_CFLAGS) - EXTRA_DIST = \ autogen.sh @@ -14,12 +6,4 @@ MAINTAINERCLEANFILES = \ aclocal.m4 \ Makefile.in -# -# binary -# -mensa_control_SOURCES = \ - mensa-control.c - -#mensa_control_LDADD = \ -# $(some_LIBS) - +SUBDIRS = src/ diff --git a/configure.ac b/configure.ac index 92c9dff..573a1cb 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_PREREQ(2.59) esyscmd([echo "define(myversion, $(dir=$(basename $(pwd)); if test \"${dir%%-trunk}\" != \"$dir\"; then echo 99999999-9; else prefix=${dir%%-[0-9]*-[0-9]}; echo ${dir##$prefix-}; fi))"]) -AC_INIT([mensa-control], myversion, [bugs@pengutronix.de]) -AC_CONFIG_SRCDIR([mensa-control.c]) +AC_INIT([mensa-control], myversion, [daniel@totalueberwachung.de]) +AC_CONFIG_SRCDIR([src]) AC_CANONICAL_BUILD AC_CANONICAL_HOST @@ -42,6 +42,8 @@ AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2]) #AC_SUBST(REQUIRES_LIBSOMETHING) #PKG_CHECK_MODULES(libsomething, $REQUIRES_LIBSOMETHING) +PKG_CHECK_MODULES(ZMQ, libzmq) + # # Debugging @@ -65,6 +67,7 @@ fi AC_CONFIG_FILES([ Makefile + src/Makefile ]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..6168a47 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,23 @@ +bin_PROGRAMS = \ + mensa-ctrl mensa-serv + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include + $(ZMQ_CFLAGS) + +# +# binary +# +ledctrl_SOURCES = \ + mensactrl.c + +ledctrl_LDADD = \ + $(ZMQ_LIBS) + +ledserv_SOURCES = \ + mensaserv.c + +ledserv_LDADD = \ + $(ZMQ_LIBS) + diff --git a/src/mensactrl.c b/src/mensactrl.c new file mode 100644 index 0000000..bb385da --- /dev/null +++ b/src/mensactrl.c @@ -0,0 +1,155 @@ +/* + * Control WS281X LEDs connected to the LCDIF + * + * Code taken from the proof-of-concept tool by + * (C) 2013 Jeroen Domburg (jeroen AT spritesmods.com) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <linux/fb.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <math.h> + +#include <zmq.h> + +struct pixel { + uint16_t x, y; + uint8_t r, g, b; +} __attribute__((packed)); + +struct ws281x_fb { + int x_res, y_res; + int fd; + uint8_t *inputfb; + uint16_t *fbmem; +}; + +//This will encode a framebuffer with per-led RGB values into the weird framebuffer +//data values we need to form the correct WS2811 driving waveform. +void encodeToFb(struct ws281x_fb *wsfb) { + int pix, col, bit, bitmask, strip, n; + int p=0; + for (pix=0; pix<wsfb->x_res; pix++) { //STRIPLEN points... + for (col=0; col<3; col++) { //...of 3 bytes (r, g. b) + bitmask=0x80; + for (bit=0; bit<8; bit++) { //...of 8 bits each. + /* At 4MHz, a bit has 5 cycles. For an 1, it's high 4, low one. For an 0, it's high one, low 4. */ + p++; /* First cycle is always 1 */ + n=0; + //Iterate through every LED-strip to fetch the bit it needs to send out. Combine those + //in n. + for (strip=0; strip<wsfb->y_res; strip++) { + if (wsfb->inputfb[(wsfb->x_res*strip*3)+(pix*3)+col]&bitmask) n|=1<<strip; + } + wsfb->fbmem[p++]=n; + wsfb->fbmem[p++]=n; //Middle 3 are dependent on bit value + wsfb->fbmem[p++]=n; + p++; /* Last cycle is always 0 */ + bitmask>>=1; //next bit in byte + } + } + } +} + + +//Helper function to set the value of a single pixel in the 'framebuffer' +//of LED pixel values. +void setPixel(struct ws281x_fb *wsfb, int pixel, int strip, int r, int g, int b) { + int pos=(strip*wsfb->x_res*3)+pixel*3; + if (strip<0 || strip>=wsfb->x_res) return; + if (pixel<0 || pixel>=wsfb->y_res) return; + wsfb->inputfb[pos++]=r; //My strips have R and G switched. + wsfb->inputfb[pos++]=g; + wsfb->inputfb[pos++]=b; +} + +static struct ws281x_fb *setup_fb(const char *devname, int x, int y) +{ + struct ws281x_fb *wsfb = malloc(sizeof(struct ws281x_fb)); + int i; + + wsfb->fd = open(devname, O_RDWR); + if (wsfb->fd < 0) { + perror("opening fb"); + free(wsfb); + exit(1); + } + wsfb->inputfb = malloc(x*y*3); + if (!wsfb->inputfb) { + free(wsfb); + exit(1); + } + memset(wsfb->inputfb, 0, x*y*3); + + wsfb->fbmem=mmap(NULL, x*5*24*2, PROT_READ|PROT_WRITE, MAP_SHARED, wsfb->fd, 0); + if (wsfb->fbmem==NULL) { + perror("mmap'ing fb"); + free(wsfb->inputfb); + free(wsfb); + exit(1); + } + for (i = 0; i < x*y*5*24; i++) { + /* Init frame buffer bit clock. */ + if (i % 5 == 0) + wsfb->fbmem[i] = 0xffff; + if (i % 5 == 4) + wsfb->fbmem[i] = 0x00; + } + + wsfb->x_res = x; + wsfb->y_res = y; + + return wsfb; +} + +int main(int argc, char *argv[]) { + struct ws281x_fb *wsfb; + void *context = zmq_ctx_new (); + void *subscriber = zmq_socket (context, ZMQ_SUB); + int rc; + + if (argc != 2) + exit(1); + + rc = zmq_connect (subscriber, "tcp://10.0.0.1:5556"); + if (rc < 0) + perror("zmq_connect"); + + rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, + NULL, 0); + if (rc < 0) + perror("zmq_connect"); + + wsfb = setup_fb(argv[1], 10, 2); + + while (1) { + struct pixel pix; + zmq_recv(subscriber, &pix, sizeof(pix), 0); + printf("(%u, %u): r=%02x g=%02x b=%02x\n", pix.x, pix.y, pix.r, pix.g, pix.b); + setPixel(wsfb, pix.x, pix.y, pix.r, pix.g, pix.b); + encodeToFb(wsfb); + } + + return 0; +} diff --git a/src/mensaserv.c b/src/mensaserv.c new file mode 100644 index 0000000..33d8ea4 --- /dev/null +++ b/src/mensaserv.c @@ -0,0 +1,112 @@ +/* + * Control WS281X LEDs connected to the LCDIF + * + * Code taken from the proof-of-concept tool by + * (C) 2013 Jeroen Domburg (jeroen AT spritesmods.com) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <linux/fb.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <math.h> + +#include <zmq.h> + +struct pixel { + uint16_t x, y; + uint8_t r, g, b; +} __attribute__((packed)); + +static void fade(void *publisher) +{ + struct pixel pix1 = { .x = 0, .y = 0, .r = 0, .g = 0, .b = 0 }; + struct pixel pix2 = { .x = 1, .y = 0, .r = 0, .g = 0, .b = 0 }; + struct pixel pix3 = { .x = 2, .y = 0, .r = 0, .g = 0, .b = 0 }; + int state = 0; + while (1) { + switch (state) { + case 0: + pix1.r++; + pix2.g++; + pix3.b++; + if (pix1.r == 255) + state++; + break; + case 1: + pix1.r--; + pix1.g++; + pix2.g--; + pix2.b++; + pix3.b--; + pix3.r++; + if (pix1.g == 255) + state++; + break; + case 2: + pix1.g--; + pix1.b++; + pix2.b--; + pix2.r++; + pix3.r--; + pix3.g++; + if (pix1.b == 255) + state++; + break; + case 3: + pix1.b--; + pix1.r++; + pix2.r--; + pix2.g++; + pix3.g--; + pix3.b++; + if (pix1.r == 255) + state = 1; + break; + } + zmq_send(publisher, &pix1, sizeof(pix1), 0); + printf("(%u, %u): r=%02x g=%02x b=%02x\n", pix1.x, pix1.y, pix1.r, pix1.g, pix1.b); + //zmq_send(publisher, &pix2, sizeof(pix2), 0); + //printf("(%u, %u): r=%02x g=%02x b=%02x\n", pix2.x, pix2.y, pix2.r, pix2.g, pix2.b); + //zmq_send(publisher, &pix3, sizeof(pix3), 0); + //printf("(%u, %u): r=%02x g=%02x b=%02x\n", pix3.x, pix3.y, pix3.r, pix3.g, pix3.b); + usleep(10000); + } +} + + +int main(void) +{ + void *context = zmq_ctx_new (); + void *publisher = zmq_socket (context, ZMQ_PUB); + int rc; + + rc = zmq_bind (publisher, "tcp://*:5556"); + if (rc < 0) + perror("zmq_bind"); + + + fade(publisher); + + return 0; +} -- GitLab