Skip to content
Snippets Groups Projects
mensactrl.c 5.24 KiB
Newer Older
daniel's avatar
daniel committed
/*
daniel's avatar
daniel committed
 * Control Mensadisplay connected to the LCDIF
daniel's avatar
daniel committed
 *
daniel's avatar
daniel committed
 * (C) 2014 Daniel Willmann <daniel@totalueberwachung.de>
daniel's avatar
daniel committed

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

daniel's avatar
daniel committed
#include "common.h"
daniel's avatar
daniel committed
#define ROWS_PER_LINE 7
#define LINES_PER_MODULE 2
#define COLS_PER_MODULE 40

daniel's avatar
daniel committed
struct mensa_fb {
daniel's avatar
daniel committed
	int x_res, y_res;
daniel's avatar
daniel committed
	int hmodules, vmodules;
daniel's avatar
daniel committed
	int fd;
	uint8_t *inputfb;
	uint16_t *fbmem;
daniel's avatar
daniel committed
	ssize_t size;
daniel's avatar
daniel committed
static void blit_area(struct mensa_fb *mensafb, const int col, const int row,
		const int width, const int height)
{
    int r, c;
    int vmpos, vpos, hmpos, hpos, pos;

    if (row < 0 || height < 0 || row + height > mensafb->y_res ||
		    col < 0 || width < 0 || col + width > mensafb->x_res)
	    return;

    for (r = row; r < row + height; r++) {
        for (c = col; c < col + width; c++) {
            /* Calculate module and position inside the module */
            vmpos = r/(LINES_PER_MODULE*ROWS_PER_LINE);
            vpos = r%(LINES_PER_MODULE*ROWS_PER_LINE);
            hmpos = c/(COLS_PER_MODULE);
            hpos = c%(COLS_PER_MODULE);

            pos = hpos + hmpos*COLS_PER_MODULE*LINES_PER_MODULE;

            if (vpos >= ROWS_PER_LINE) {
                vpos -= ROWS_PER_LINE;
                pos += COLS_PER_MODULE;
            }

daniel's avatar
daniel committed
	    /* Invert order */
            pos = (LINES_PER_MODULE * COLS_PER_MODULE * mensafb->hmodules - 1) - pos;

	    /* Add in row offset */
            pos = pos + vpos*(mensafb->hmodules*COLS_PER_MODULE*LINES_PER_MODULE);

daniel's avatar
daniel committed

	    if (mensafb->inputfb[c + r * mensafb->x_res] == 0) {
                /* clear bit */
daniel's avatar
daniel committed
                mensafb->fbmem[pos] &= ~(1<<(mensafb->vmodules - 1 - vmpos));
daniel's avatar
daniel committed
            } else {
                /* set bit */
daniel's avatar
daniel committed
                mensafb->fbmem[pos] |= (1<<(mensafb->vmodules - 1 - vmpos));
daniel's avatar
daniel committed
            }
        }
    }
}


void encodeToFb(struct mensa_fb *mensafb)
{
	blit_area(mensafb, 0, 0, mensafb->x_res, mensafb->y_res);
daniel's avatar
daniel committed
}
daniel's avatar
daniel committed
//	int pix, row, cols, idx, fbidx, i, ledrow;
//	uint16_t pattern;
//
//	for (fbidx = 0; fbidx < mensafb->x_res * mensafb->y_res / mensafb->modules; fbidx++) {
//		cols = mensafb->x_res * 2;
//
//		row = fbidx / cols;
//		ledrow = row;
//		pix = fbidx % cols;
//
//		if (pix / 40 % 2 == 0) {
//			pix = pix + (pix / 40 * 40);
//		} else {
//			pix = pix + (pix / 40 * 40) + 40;
//			row = row + 7;
//		}
//
//
//		pattern = 0;
//		for (i = 0; i < mensafb->modules; i++) {
//			idx = row * mensafb->x_res + pix + i * mensafb->x_res * 14;
//			if (mensafb->inputfb[idx] > 0)
//				pattern |= 1 << i;
//		}
//			/* During update of the next line we want to display the
//			 * content of the last one */
//			pattern |= (ledrow-1 % 7) << 5;
//
//			mensafb->fbmem[fbidx] = pattern;
//	}
//}
daniel's avatar
daniel committed
void setPixel(struct mensa_fb *mensafb, int col, int row, uint8_t bright)
{
	int idx = row * mensafb->x_res + col;

	if (col < 0 || col >= mensafb->x_res)
		return;
	if (row < 0 || row >= mensafb->y_res)
		return;

	mensafb->inputfb[idx] = bright;
daniel's avatar
daniel committed
static struct mensa_fb *setup_fb(const char *devname, int hmodules, int vmodules)
daniel's avatar
daniel committed
{
daniel's avatar
daniel committed
	struct mensa_fb *mensafb = malloc(sizeof(struct mensa_fb));
daniel's avatar
daniel committed
	int i;

daniel's avatar
daniel committed
	mensafb->x_res = COLS_PER_MODULE * hmodules;
	mensafb->y_res = ROWS_PER_LINE * LINES_PER_MODULE * vmodules;
	mensafb->size = mensafb->x_res * ROWS_PER_LINE * LINES_PER_MODULE;
daniel's avatar
daniel committed
	mensafb->fd = open(devname, O_RDWR);
	if (mensafb->fd < 0) {
daniel's avatar
daniel committed
		perror("opening fb");
daniel's avatar
daniel committed
		free(mensafb);
daniel's avatar
daniel committed
		exit(1);
	}
daniel's avatar
daniel committed
	mensafb->inputfb = malloc(mensafb->x_res * mensafb->y_res);
daniel's avatar
daniel committed
	if (!mensafb->inputfb) {
		free(mensafb);
daniel's avatar
daniel committed
		exit(1);
	}
daniel's avatar
daniel committed
	memset(mensafb->inputfb, 0, mensafb->x_res * mensafb->y_res);
daniel's avatar
daniel committed
	mensafb->fbmem=mmap(NULL, mensafb->size * 2,
			PROT_READ|PROT_WRITE, MAP_SHARED, mensafb->fd, 0);
daniel's avatar
daniel committed
	if (mensafb->fbmem==NULL) {
daniel's avatar
daniel committed
		perror("mmap'ing fb");
daniel's avatar
daniel committed
		free(mensafb->inputfb);
		free(mensafb);
daniel's avatar
daniel committed
		exit(1);
	}
daniel's avatar
daniel committed
	for (i = 0; i < mensafb->size ; i++)
daniel's avatar
daniel committed
		mensafb->fbmem[i] = ((6 + i / (mensafb->x_res * LINES_PER_MODULE)) % 7)<<5;
daniel's avatar
daniel committed
	mensafb->hmodules = hmodules;
	mensafb->vmodules = vmodules;
daniel's avatar
daniel committed
	return mensafb;
daniel's avatar
daniel committed
}

int main(int argc, char *argv[]) {
daniel's avatar
daniel committed
	struct mensa_fb *mensafb;
daniel's avatar
daniel committed
	void *context = zmq_ctx_new ();
daniel's avatar
daniel committed
	void *responder = zmq_socket (context, ZMQ_REP);
daniel's avatar
daniel committed
	int rc;

	if (argc != 2)
		exit(1);

daniel's avatar
daniel committed
	rc = zmq_bind (responder, "tcp://*:5556");
daniel's avatar
daniel committed
	if (rc < 0)
daniel's avatar
daniel committed
		perror("zmq_bind");
daniel's avatar
daniel committed
	mensafb = setup_fb(argv[1], 12, 5);
daniel's avatar
daniel committed

	while (1) {
		struct pixel pix;
daniel's avatar
daniel committed
		zmq_recv(responder, &pix, sizeof(pix), 0);
daniel's avatar
daniel committed
		setPixel(mensafb, pix.x, pix.y, pix.bright);
daniel's avatar
daniel committed
		zmq_send(responder, &pix, sizeof(pix), 0);
daniel's avatar
daniel committed
		encodeToFb(mensafb);
daniel's avatar
daniel committed
	}

	return 0;
}