3 // ****************************************************************************
4 // vfdclient.h (C) 1992-2003 Christophe de Dinechin (ddd)
6 // ****************************************************************************
10 // Client-side API for talking to the Vaccuum Fluorescent Display (VFD)
19 // ****************************************************************************
20 // This document is confidential.
21 // Do not redistribute without written permission
22 // ****************************************************************************
24 // * Revision : $Revision$
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>
41 #error VFDCLIENT (client name) must be set
44 #error VFDOPTIONS (option file) must be set
47 #error VFDCONFIG (default configuration name) must be set
51 // ============================================================================
55 // ============================================================================
57 static inline void Error(char *msg
)
58 // ----------------------------------------------------------------------------
59 // Report a problem of some sort
60 // ----------------------------------------------------------------------------
67 static int Help2(char *msg1
, char *msg2
)
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
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);
79 printf("*** %s%s\n", msg1
, msg2
);
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 // ----------------------------------------------------------------------------
115 for (arg
= 1; arg
< argc
; arg
++)
117 char *opt
= argv
[arg
];
120 // Skip '-' in front of options.
121 while (opt
[0] == '-')
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
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]),""))
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 // ----------------------------------------------------------------------------
145 struct sockaddr_in serv_addr
;
146 struct hostent
*server
;
149 sockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
151 Error(VFDCLIENT
"(socket)");
152 server
= gethostbyname(server_name
);
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
,
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);
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);
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)");
192 static void vfd_cmd(int fd
, const char *fmt
, ...)
193 // ----------------------------------------------------------------------------
194 // Send a formatted message onto a VFD socket
195 // ----------------------------------------------------------------------------
200 bzero(buffer
, sizeof(buffer
));
201 vsnprintf(buffer
, sizeof(buffer
)-1, fmt
, 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 // ----------------------------------------------------------------------------
217 bzero(buffer
, sizeof(buffer
));
218 vsnprintf(buffer
, sizeof(buffer
)-1, fmt
, va
);
220 ptr
= strchr(buffer
, '\n');
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 // ----------------------------------------------------------------------------
239 static vfd_glyph_extent
vfd_printf_area(int vfd
, const char *fmt
, ...)
240 // ----------------------------------------------------------------------------
241 // Compute the area occupied by a given text
242 // ----------------------------------------------------------------------------
246 vfd_glyph_extent extent
;
250 bzero(buffer
, sizeof(buffer
));
251 vsnprintf(buffer
, sizeof(buffer
)-1, fmt
, va
);
253 ptr
= strchr(buffer
, '\n');
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
);
267 typedef struct vfd_configuration
268 // ----------------------------------------------------------------------------
269 // Description of a VFD configuration
270 // ----------------------------------------------------------------------------
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
;
285 vfd_cmd(vfd
, "N%s\n", name
);
286 bzero(buffer
, sizeof(buffer
));
287 n
= read(vfd
, buffer
, sizeof(buffer
)-1);
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)
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
);
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
471 vfd_glyph_extent extent
;
473 vfd_cmd(vfd
, "I%d:%s\n", c
, str
);
475 n
= read(vfd
, buffer
, sizeof(buffer
)-1);
477 Error(VFDCLIENT
"(text2glyph-read)");
478 extent
.w
= extent
.h
= 0;
479 sscanf(buffer
, "W%i H%i", &extent
.w
, &extent
.h
);
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 */