root/branches/volker_dev/drv_LEDMatrix.c

Revision 774, 7.5 kB (checked in by michael, 23 months ago)

compiler warnings on x86_64 fixed

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * LED matrix driver for LCD4Linux
5 * (see http://www.harbaum.org/till/ledmatrix for hardware)
6 *
7 * Copyright (C) 2006 Till Harbaum <till@harbaum.org>
8 *
9 * This file is part of LCD4Linux.
10 *
11 * LCD4Linux is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * LCD4Linux is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27/*
28 *
29 * exported fuctions:
30 *
31 * struct DRIVER drv_LEDMatrix
32 *
33 */
34
35/*
36 * Options:
37 * IPAddress
38 */
39
40#include "config.h"
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45#include <errno.h>
46#include <unistd.h>
47#include <termios.h>
48#include <fcntl.h>
49#include <sys/time.h>
50
51/* include network specific headers */
52#include <arpa/inet.h>
53#include <sys/socket.h>
54#include <netinet/in.h>
55#include <sys/select.h>
56#include <netdb.h>
57
58#include "debug.h"
59#include "cfg.h"
60#include "qprintf.h"
61#include "plugin.h"
62#include "widget.h"
63#include "widget_text.h"
64#include "widget_icon.h"
65#include "widget_bar.h"
66#include "drv.h"
67#include "drv_generic_graphic.h"
68
69/* display command bytes */
70#define DSP_CMD_ECHO  0
71#define DSP_CMD_NOP   1
72#define DSP_CMD_IMAGE 2
73#define DSP_CMD_ACK   3
74#define DSP_CMD_IR    4
75#define DSP_CMD_BEEP  5
76
77#define DSP_DEFAULT_PORT 4711
78
79#define DSP_MEM (80 * 32 * 2 / 8)
80
81#define DEFAULT_X_OFFSET   1  /* with a font width of 6 */
82
83static char Name[] = "LEDMatrix";
84static char *IPAddress = NULL;
85static int sock = -1;
86static struct sockaddr_in dsp_addr;
87static unsigned char tx_buffer[DSP_MEM + 1];
88static int port = DSP_DEFAULT_PORT;
89
90static void drv_LEDMatrix_blit(const int row, const int col, const int height, const int width)
91{
92    int r, c, i;
93    fd_set rfds;
94    struct timeval tv;
95    unsigned char reply[256];
96    struct sockaddr_in cli_addr;
97    socklen_t fromlen;
98    int ack = 0;
99    int timeout = 10;
100
101    for (r = row; r < row + height; r++) {
102  for (c = col; c < col + width; c++) {
103      /* LEDMATRIX supports three colors: 10b == green, 01b == red, 11b == amber */
104
105      unsigned char color = 0;
106      RGBA p = drv_generic_graphic_rgb(r, c);
107      if (p.G >= 128)
108    color |= 0x80;
109      if (p.R >= 128)
110    color |= 0x40;
111      /* ignore blue ... */
112
113      tx_buffer[1 + 20 * r + c / 4] &= ~(0xc0 >> (2 * (c & 3)));
114      tx_buffer[1 + 20 * r + c / 4] |= color >> (2 * (c & 3));
115  }
116    }
117
118    /* scan entire display */
119    tx_buffer[0] = DSP_CMD_IMAGE;
120
121    do {
122
123  if ((sendto(sock, tx_buffer, DSP_MEM + 1, 0, (struct sockaddr *) &dsp_addr, sizeof(dsp_addr))) != DSP_MEM + 1)
124      error("%s: sendto error on socket", Name);
125
126  /* now wait for reply */
127
128  FD_ZERO(&rfds);
129  FD_SET(sock, &rfds);
130  tv.tv_sec = 0;
131  tv.tv_usec = 100000;
132
133  /* wait 1 sec for ack */
134  if ((i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) < 0) {
135      info("%s: Select error: %s", Name, strerror(errno));
136  }
137
138  if (FD_ISSET(sock, &rfds)) {
139      /* wait for ack */
140      fromlen = sizeof(dsp_addr);
141      i = recvfrom(sock, reply, sizeof(reply), 0, (struct sockaddr *) &cli_addr, &fromlen);
142      if (i < 0) {
143    info("%s: Receive error: %s", Name, strerror(errno));
144      } else {
145    if ((i == 2) && (reply[0] == DSP_CMD_ACK) && (reply[1] == DSP_CMD_IMAGE)) {
146        ack = 1;
147    } else if ((i > 1) && (reply[0] == DSP_CMD_IR)) {
148        /* maybe used later: */
149        /* ir_receive(reply+1, i-1); */
150    } else {
151        info("%s: Unexpected reply message", Name);
152    }
153      }
154  }
155  timeout--;
156    } while ((!ack) && (timeout > 0));
157
158    if (timeout == 0) {
159  error("%s: display reply timeout", Name);
160    }
161}
162
163static int drv_LEDMatrix_start(const char *section)
164{
165    char *s;
166    struct sockaddr_in cli_addr;
167    struct hostent *hp;
168    int val;
169
170    IPAddress = cfg_get(section, "IPAddress", NULL);
171    if (IPAddress == NULL || *IPAddress == '\0') {
172  error("%s: no '%s.IPAddress' entry from %s", Name, section, cfg_source());
173  return -1;
174    }
175
176    if (cfg_number(section, "Port", 0, 0, 65535, &val) > 0) {
177  info("%s: port set to %d", Name, val);
178  port = val;
179    } else {
180  info("%s: using default port %d", Name, port);
181    }
182
183    /* display size is hard coded */
184    DCOLS = 80;
185    DROWS = 32;
186
187    if (sscanf(s = cfg_get(section, "font", "6x8"), "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) {
188  error("%s: bad %s.Font '%s' from %s", Name, section, s, cfg_source());
189  free(s);
190  return -1;
191    }
192    free(s);
193
194    /* contact display */
195    info("%s: contacting %s", Name, IPAddress);
196
197    /* try to resolve as a hostname */
198    if ((hp = gethostbyname(IPAddress)) == NULL) {
199  error("%s: unable to resolve hostname %s: %s", Name, IPAddress, strerror(errno));
200  return -1;
201    }
202
203    /* open datagram socket */
204    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
205  error("%s: could not create socket: %s", Name, strerror(errno));
206  return -1;
207    }
208
209    memset((char *) &dsp_addr, 0, sizeof(dsp_addr));
210    dsp_addr.sin_family = AF_INET;
211    dsp_addr.sin_addr.s_addr = *(int *) hp->h_addr;
212    dsp_addr.sin_port = htons(port);
213
214    cli_addr.sin_family = AF_INET;
215    cli_addr.sin_addr.s_addr = htons(INADDR_ANY);
216    cli_addr.sin_port = htons(port);
217
218    if (bind(sock, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) {
219  error("%s: can't bind local address: %s", Name, strerror(errno));
220  return -1;
221    }
222
223    memset(tx_buffer, 0, sizeof(tx_buffer));
224
225    return 0;
226}
227
228
229
230/****************************************/
231/***            plugins               ***/
232/****************************************/
233
234/* none at the moment... */
235
236
237/****************************************/
238/***        widget callbacks          ***/
239/****************************************/
240
241
242/* using drv_generic_graphic_draw(W) */
243/* using drv_generic_graphic_icon_draw(W) */
244/* using drv_generic_graphic_bar_draw(W) */
245
246
247/****************************************/
248/***        exported functions        ***/
249/****************************************/
250
251
252/* list models */
253int drv_LEDMatrix_list(void)
254{
255    return 0;
256}
257
258
259/* initialize driver & display */
260int drv_LEDMatrix_init(const char *section, const __attribute__ ((unused))
261           int quiet)
262{
263    WIDGET_CLASS wc;
264    int ret;
265
266    /* real worker functions */
267    drv_generic_graphic_real_blit = drv_LEDMatrix_blit;
268
269    /* start display */
270    if ((ret = drv_LEDMatrix_start(section)) != 0)
271  return ret;
272
273    /* initialize generic graphic driver */
274    if ((ret = drv_generic_graphic_init(section, Name)) != 0)
275  return ret;
276
277    /* register text widget */
278    wc = Widget_Text;
279    wc.draw = drv_generic_graphic_draw;
280    widget_register(&wc);
281
282    /* register icon widget */
283    wc = Widget_Icon;
284    wc.draw = drv_generic_graphic_icon_draw;
285    widget_register(&wc);
286
287    /* register bar widget */
288    wc = Widget_Bar;
289    wc.draw = drv_generic_graphic_bar_draw;
290    widget_register(&wc);
291
292    /* register plugins */
293    /* none at the moment... */
294
295
296    return 0;
297}
298
299
300/* close driver & display */
301int drv_LEDMatrix_quit(const __attribute__ ((unused))
302           int quiet)
303{
304
305    info("%s: shutting down.", Name);
306    drv_generic_graphic_quit();
307
308    if (sock != -1)
309  close(sock);
310
311    return (0);
312}
313
314
315DRIVER drv_LEDMatrix = {
316    .name = Name,
317    .list = drv_LEDMatrix_list,
318    .init = drv_LEDMatrix_init,
319    .quit = drv_LEDMatrix_quit,
320};
Note: See TracBrowser for help on using the browser.