Added support for DE200C VFD
[lcdproc-de200c.git] / server / drivers / de200c-vfd / clients / vfdclient.h
blobbb969147099a03472430bd1f5b5582a86ec63448
1 #ifndef VFDCLIENT_H
2 #define VFDCLIENT_H
3 // ****************************************************************************
4 // vfdclient.h (C) 1992-2003 Christophe de Dinechin (ddd)
5 // VFD800 project
6 // ****************************************************************************
7 //
8 // File Description:
9 //
10 // Client-side API for talking to the Vaccuum Fluorescent Display (VFD)
11 // server
12 //
13 //
14 //
15 //
16 //
17 //
18 //
19 // ****************************************************************************
20 // This document is confidential.
21 // Do not redistribute without written permission
22 // ****************************************************************************
23 // * File : $RCSFile$
24 // * Revision : $Revision$
25 // * Date : $Date$
26 // ****************************************************************************
28 // The protocol is simple enough that everything is implemented in a .h file
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <netdb.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <strings.h>
38 #include <string.h>
40 #ifndef VFDCLIENT
41 #error VFDCLIENT (client name) must be set
42 #endif
43 #ifndef VFDOPTIONS
44 #error VFDOPTIONS (option file) must be set
45 #endif
46 #ifndef VFDCONFIG
47 #error VFDCONFIG (default configuration name) must be set
48 #endif
51 // ============================================================================
52 //
53 // Helper functions
54 //
55 // ============================================================================
57 static inline void Error(char *msg)
58 // ----------------------------------------------------------------------------
59 // Report a problem of some sort
60 // ----------------------------------------------------------------------------
62 perror(msg);
63 exit(1);
67 static int Help2(char *msg1, char *msg2)
68 // ----------------------------------------------------------------------------
69 // Show help
70 // ----------------------------------------------------------------------------
72 if (msg1)
73 printf("*** %s%s\n", msg1, msg2);
74 printf("Usage: tvsetup [options]\n");
75 #define OPTION(name, usage, code) printf("%15s: %s\n", #name, usage);
76 #define FLAG(name, usage, code) printf("%15s: %s\n", "[no]" #name, usage);
77 #include VFDOPTIONS
78 if (msg1)
79 printf("*** %s%s\n", msg1, msg2);
80 exit(0);
81 return 0;
85 #define Help1(msg) Help2(msg, "")
86 #define Help() Help2(NULL, "")
89 static int force_x = -1;
90 static int force_y = -1;
91 static int force_w = -1;
92 static int force_h = -1;
93 static int force_p = -1;
94 static char *server = "localhost";
95 static int port = 12568;
96 static char *cfg = VFDCONFIG;
97 static int verbose = 0;
99 #define dprintf verbose && printf
102 // ============================================================================
104 // Client-side VFD API
106 // ============================================================================
108 static void vfd_options(int argc, char **argv)
109 // ----------------------------------------------------------------------------
110 // Process options for the VFD parameters
111 // ----------------------------------------------------------------------------
113 // Parse options
114 int arg;
115 for (arg = 1; arg < argc; arg++)
117 char *opt = argv[arg];
118 int boolval = 0;
120 // Skip '-' in front of options.
121 while (opt[0] == '-')
122 opt++;
124 #define OPTION(name, usage, code) \
125 if (!strcmp(opt, #name)) { code; } else
126 #define FLAG(name, usage, code) \
127 if (!strcmp(opt, #name)) { boolval = 1; code; } else \
128 if (!strcmp(opt, "no" #name)) { boolval = 0; code; } else
129 #define BOOL boolval
130 #define INT ((++arg < argc) ? atol(argv[arg]) : Help2("Missing int value", argv[arg]))
131 #define STRING ((++arg < argc) ? argv[arg] : (Help2("Missing string", argv[arg]),""))
132 #include VFDOPTIONS
134 Help2 ("Unknown option:", boolval ? argv[arg] : argv[arg]);
139 static int vfd_open(char *server_name, int port)
140 // ----------------------------------------------------------------------------
141 // Open the VFD on the given server and port
142 // ----------------------------------------------------------------------------
144 int sockfd,n;
145 struct sockaddr_in serv_addr;
146 struct hostent *server;
147 char buffer[256];
149 sockfd = socket(AF_INET, SOCK_STREAM, 0);
150 if (sockfd < 0)
151 Error(VFDCLIENT "(socket)");
152 server = gethostbyname(server_name);
153 if (server == NULL)
154 Error(VFDCLIENT "(gethostbyname)");
155 bzero((char *) &serv_addr, sizeof(serv_addr));
156 serv_addr.sin_family = AF_INET;
157 bcopy((char *)server->h_addr,
158 (char *)&serv_addr.sin_addr.s_addr,
159 server->h_length);
160 serv_addr.sin_port = htons(port);
161 if (connect(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
162 Error(VFDCLIENT "(connect)");
164 // Check who we are talking to
165 if (write(sockfd, "V", 1) < 0)
166 Error(VFDCLIENT "(open-write)");
167 bzero(buffer, sizeof(buffer));
168 n = read(sockfd, buffer, sizeof(buffer)-1);
169 if (n < 0)
170 Error(VFDCLIENT "(open-read)");
171 if (!strstr(buffer, "Ready"))
173 fprintf(stderr, "Protocol error: Got '%s'\n", buffer);
174 Error(VFDCLIENT "(vfd800 protocol)");
176 if (!strstr(buffer, "VFD800 Server"))
178 n = read(sockfd, buffer, sizeof(buffer)-1);
179 if (n < 0)
180 Error(VFDCLIENT "(open-read)");
181 if (!strstr(buffer, "VFD800 Server"))
183 fprintf(stderr, "Protocol error(2): Got '%s'\n", buffer);
184 Error(VFDCLIENT "(vfd800 protocol2)");
188 return sockfd;
192 static void vfd_cmd(int fd, const char *fmt, ...)
193 // ----------------------------------------------------------------------------
194 // Send a formatted message onto a VFD socket
195 // ----------------------------------------------------------------------------
197 char buffer[256];
198 va_list va;
199 va_start(va, fmt);
200 bzero(buffer, sizeof(buffer));
201 vsnprintf(buffer, sizeof(buffer)-1, fmt, va);
202 va_end(va);
203 if (write(fd, buffer, strlen(buffer)) < 0)
204 Error(VFDCLIENT "(cmd-write)");
208 static void vfd_printf(int vfd, int x, int y, const char *fmt, ...)
209 // ----------------------------------------------------------------------------
210 // Send a formatted message as text onto a VFD
211 // ----------------------------------------------------------------------------
213 char buffer[256];
214 char *ptr;
215 va_list va;
216 va_start(va, fmt);
217 bzero(buffer, sizeof(buffer));
218 vsnprintf(buffer, sizeof(buffer)-1, fmt, va);
219 va_end(va);
220 ptr = strchr(buffer, '\n');
221 if (ptr) *ptr = 0;
222 vfd_cmd(vfd, "X%dY%dT", x, y);
223 if (write(vfd, buffer, strlen(buffer)) < 0 ||
224 write(vfd, "\n", 1) < 0)
225 Error(VFDCLIENT "(printf-write)");
229 typedef struct vfd_glyph_extent
230 // ----------------------------------------------------------------------------
231 // Information about the size of a glyph
232 // ----------------------------------------------------------------------------
234 int w;
235 int h;
236 } vfd_glyph_extent;
239 static vfd_glyph_extent vfd_printf_area(int vfd, const char *fmt, ...)
240 // ----------------------------------------------------------------------------
241 // Compute the area occupied by a given text
242 // ----------------------------------------------------------------------------
244 char buffer[256];
245 char *ptr;
246 vfd_glyph_extent extent;
248 va_list va;
249 va_start(va, fmt);
250 bzero(buffer, sizeof(buffer));
251 vsnprintf(buffer, sizeof(buffer)-1, fmt, va);
252 va_end(va);
253 ptr = strchr(buffer, '\n');
254 if (ptr) *ptr = 0;
255 if (write(vfd, "A", 1) < 0 ||
256 write(vfd, buffer, strlen(buffer)) < 0 ||
257 write(vfd, "\n", 1) < 0)
258 Error(VFDCLIENT "(printf-area-write)");
259 if (read(vfd, buffer, sizeof(buffer)) < 0)
260 Error(VFDCLIENT "(printf-area-read)");
261 extent.w = extent.h = 0;
262 sscanf(buffer, "W%i H%i", &extent.w, &extent.h);
263 return extent;
267 typedef struct vfd_configuration
268 // ----------------------------------------------------------------------------
269 // Description of a VFD configuration
270 // ----------------------------------------------------------------------------
272 int x, y, w, h;
273 int priority;
274 } vfd_configuration;
277 static inline vfd_configuration vfd_configure (int vfd, char *name)
278 // ----------------------------------------------------------------------------
279 // Send a configuration request, and get back coordinates
280 // ----------------------------------------------------------------------------
282 vfd_configuration cfg;
283 char buffer[256];
284 int n;
285 vfd_cmd(vfd, "N%s\n", name);
286 bzero(buffer, sizeof(buffer));
287 n = read(vfd, buffer, sizeof(buffer)-1);
288 if (n < 0)
289 Error(VFDCLIENT "(configuration-read)");
290 cfg.x = cfg.y = cfg.w = cfg.h = cfg.priority = 0;
291 sscanf(buffer, "X%i Y%i W%i H%i P%i",
292 &cfg.x, &cfg.y, &cfg.w, &cfg.h, &cfg.priority);
294 // Check for local overrides
295 if (force_x >= 0 || force_y >= 0 ||
296 force_w >= 0 || force_h >= 0 || force_p >= 0)
298 if (force_x >= 0)
299 cfg.x = force_x;
300 if (force_y >= 0)
301 cfg.y = force_y;
302 if (force_w >= 0)
303 cfg.w = force_w;
304 if (force_h >= 0)
305 cfg.h = force_h;
306 if (force_p >= 0)
307 cfg.priority = force_p;
309 // Send updated area to the server
310 vfd_cmd(vfd, "M+CX%dY%dW%dH%dZ%dFRD",
311 cfg.x, cfg.y, cfg.w, cfg.h, cfg.priority);
314 return cfg;
318 static inline void vfd_update(int vfd)
319 // ----------------------------------------------------------------------------
320 // Request a screen update
321 // ----------------------------------------------------------------------------
323 if (write(vfd, "U", 1) < 0)
324 Error(VFDCLIENT "(update)");
328 static inline void vfd_clear(int vfd)
329 // ----------------------------------------------------------------------------
330 // Clear the screen
331 // ----------------------------------------------------------------------------
333 if (write(vfd, "C", 1) < 0)
334 Error(VFDCLIENT "(clear)");
338 static inline void vfd_select_mask(int vfd)
339 // ----------------------------------------------------------------------------
340 // Select the mask for the next drawing operations
341 // ----------------------------------------------------------------------------
343 if (write(vfd, "M", 1) < 0)
344 Error(VFDCLIENT "(select_mask)");
348 static inline void vfd_select_display(int vfd)
349 // ----------------------------------------------------------------------------
350 // Select the display contents for next drawing operations
351 // ----------------------------------------------------------------------------
353 if (write(vfd, "D", 1) < 0)
354 Error(VFDCLIENT "(select_display)");
358 static inline void vfd_set_color(int vfd, int color)
359 // ----------------------------------------------------------------------------
360 // Select color: 1 = bright, 0 = dark
361 // ----------------------------------------------------------------------------
363 vfd_cmd(vfd, "%c", color ? '+' : '-');
367 static inline void vfd_set_brightness(int vfd, float brightness)
368 // ----------------------------------------------------------------------------
369 // Select color: 1 = bright, 0 = dark
370 // ----------------------------------------------------------------------------
372 vfd_cmd(vfd, "B%d", (int) (brightness * 255));
376 static inline void vfd_reverse(int vfd, int x, int y, int w, int h)
377 // ----------------------------------------------------------------------------
378 // Invert the selected area
379 // ----------------------------------------------------------------------------
381 vfd_cmd(vfd, "X%dY%dW%dH%d*", x, y, w, h);
385 static inline void vfd_set_priority(int vfd, int priority)
386 // ----------------------------------------------------------------------------
387 // Select client priority (higher = more visible)
388 // ----------------------------------------------------------------------------
390 vfd_cmd(vfd, "Z%d", priority);
394 static inline void vfd_rectangle(int vfd,
395 int x, int y, int w, int h)
396 // ----------------------------------------------------------------------------
397 // Draw a rectangle outline
398 // ----------------------------------------------------------------------------
400 vfd_cmd(vfd, "X%dY%dW%dH%dOR", x, y, w, h);
404 static inline void vfd_fill_rectangle(int vfd,
405 int x, int y, int w, int h)
406 // ----------------------------------------------------------------------------
407 // Draw a filled rectangle
408 // ----------------------------------------------------------------------------
410 vfd_cmd(vfd, "X%dY%dW%dH%dFR", x, y, w, h);
414 static inline void vfd_ellipse(int vfd,
415 int x, int y, int w, int h)
416 // ----------------------------------------------------------------------------
417 // Draw an ellipse outline
418 // ----------------------------------------------------------------------------
420 vfd_cmd(vfd, "X%dY%dW%dH%dOE", x, y, w, h);
424 static inline void vfd_fill_ellipse(int vfd,
425 int x, int y, int w, int h)
426 // ----------------------------------------------------------------------------
427 // Draw a filled ellipse
428 // ----------------------------------------------------------------------------
430 vfd_cmd(vfd, "X%dY%dW%dH%dFE", x, y, w, h);
434 static inline void vfd_point(int vfd, int x, int y, int w, int h)
435 // ----------------------------------------------------------------------------
436 // Plot a single pixel
437 // ----------------------------------------------------------------------------
439 vfd_cmd(vfd, "X%dY%dP", x, y);
443 static inline void vfd_line(int vfd, int x, int y, int dx, int dy)
444 // ----------------------------------------------------------------------------
445 // Draw a line
446 // ----------------------------------------------------------------------------
448 vfd_cmd(vfd, "X%dY%dW%dH%dL", x, y, dx, dy);
452 static void vfd_define_glyph(int vfd, int c, int w, int h, char *bytes)
453 // ----------------------------------------------------------------------------
454 // Send a glyph definition to the server
455 // ----------------------------------------------------------------------------
457 int n, sz = w * h;
458 vfd_cmd(vfd, "G %d %d %d ", c, w, h);
459 for (n = 0; n < sz; n++)
460 vfd_cmd(vfd, "%02X", (unsigned char) *bytes++);
464 static vfd_glyph_extent vfd_text_to_glyph(int vfd, int c, char *str)
465 // ----------------------------------------------------------------------------
466 // Create a glyph from a combination of glyphs
467 // ----------------------------------------------------------------------------
469 char buffer[256];
470 int n;
471 vfd_glyph_extent extent;
473 vfd_cmd(vfd, "I%d:%s\n", c, str);
475 n = read(vfd, buffer, sizeof(buffer)-1);
476 if (n < 0)
477 Error(VFDCLIENT "(text2glyph-read)");
478 extent.w = extent.h = 0;
479 sscanf(buffer, "W%i H%i", &extent.w, &extent.h);
481 return extent;
485 static void vfd_select_font(int vfd, int font)
486 // ----------------------------------------------------------------------------
487 // Select the fontset for this client (0 = mono, 1 = proportional)
488 // ----------------------------------------------------------------------------
490 vfd_cmd(vfd, "J%d", font);
494 #endif /* VFDCLIENT_H */