root/trunk/drv_Sample.c

Revision 840, 13.4 kB (checked in by michael, 15 months ago)

email address changed

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * sample lcd4linux driver
5 *
6 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
7 * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
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_Sample
32 *
33 */
34
35#include "config.h"
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <unistd.h>
40#include <string.h>
41#include <errno.h>
42
43#include "debug.h"
44#include "cfg.h"
45#include "qprintf.h"
46#include "udelay.h"
47#include "plugin.h"
48#include "widget.h"
49#include "widget_text.h"
50#include "widget_icon.h"
51#include "widget_bar.h"
52#include "drv.h"
53
54/* text mode display? */
55#include "drv_generic_text.h"
56
57/* graphic display? */
58#include "drv_generic_graphic.h"
59
60/* GPO's? */
61#include "drv_generic_gpio.h"
62
63/* serial port? */
64#include "drv_generic_serial.h"
65
66/* parallel port? */
67#include "drv_generic_parport.h"
68
69/* i2c bus? */
70#ifdef WITH_I2C
71#include "drv_generic_i2c.h"
72#endif
73
74
75static char Name[] = "Sample";
76
77
78/* for parallel port displays only */
79/* use whatever lines you need */
80static unsigned char SIGNAL_RS;
81static unsigned char SIGNAL_EX;
82
83
84
85/****************************************/
86/***  hardware dependant functions    ***/
87/****************************************/
88
89/* low-level parallel port stuff */
90/* example for sending one byte over the wire */
91static void drv_Sample_bang(const unsigned int data)
92{
93    /* put data on DB1..DB8 */
94    drv_generic_parport_data(data & 0xff);
95
96    /* set/clear some signals */
97    drv_generic_parport_control(SIGNAL_RS, SIGNAL_RS);
98
99    /* data setup time (e.g. 200 ns) */
100    ndelay(200);
101
102    /* send byte */
103    /* signal pulse width 500ns */
104    drv_generic_parport_toggle(SIGNAL_EX, 1, 500);
105
106    /* wait for command completion (e.g. 100 us) */
107    udelay(100);
108}
109
110
111static int drv_Sample_open(const char *section)
112{
113    /* open serial port */
114    /* don't mind about device, speed and stuff, this function will take care of */
115
116    if (drv_generic_serial_open(section, Name, 0) < 0)
117  return -1;
118
119
120    /* opening the parallel port is a bit more tricky: */
121    /* you have to do all the bit-banging yourself... */
122
123    if (drv_generic_parport_open(section, Name) != 0) {
124  error("%s: could not initialize parallel port!", Name);
125  return -1;
126    }
127
128    /* read the wiring from config */
129    if ((SIGNAL_EX = drv_generic_parport_wire_ctrl("EX", "STROBE")) == 0xff)
130  return -1;
131    if ((SIGNAL_RS = drv_generic_parport_wire_ctrl("RS", "INIT")) == 0xff)
132  return -1;
133
134    /* clear all signals */
135    drv_generic_parport_control(SIGNAL_EX | SIGNAL_RS, 0);
136
137    /* set direction: write */
138    drv_generic_parport_direction(0);
139
140    return 0;
141}
142
143
144static int drv_Sample_close(void)
145{
146    /* close whatever port you've opened */
147    drv_generic_parport_close();
148    drv_generic_serial_close();
149
150    return 0;
151}
152
153
154/* dummy function that sends something to the display */
155static void drv_Sample_send(const char *data, const unsigned int len)
156{
157    unsigned int i;
158
159    /* send data to the serial port is easy... */
160    drv_generic_serial_write(data, len);
161
162    /* sending data to the parallel port is a bit more tricky... */
163    for (i = 0; i < len; i++) {
164  drv_Sample_bang(*data++);
165    }
166}
167
168
169/* text mode displays only */
170static void drv_Sample_clear(void)
171{
172    char cmd[1];
173
174    /* do whatever is necessary to clear the display */
175    /* assume 0x01 to be a 'clear display' command */
176    cmd[0] = 0x01;
177    drv_Sample_send(cmd, 1);
178}
179
180
181/* text mode displays only */
182static void drv_Sample_write(const int row, const int col, const char *data, int len)
183{
184    char cmd[3];
185
186    /* do the cursor positioning here */
187    /* assume 0x02 to be a 'Goto' command */
188    cmd[0] = 0x02;
189    cmd[1] = row;
190    cmd[2] = col;
191    drv_Sample_send(cmd, 3);
192
193    /* send string to the display */
194    drv_Sample_send(data, len);
195
196}
197
198/* text mode displays only */
199static void drv_Sample_defchar(const int ascii, const unsigned char *matrix)
200{
201    char cmd[10];
202    int i;
203
204    /* call the 'define character' function */
205    /* assume 0x03 to be the 'defchar' command */
206    cmd[0] = 0x03;
207    cmd[1] = ascii;
208
209    /* send bitmap to the display */
210    for (i = 0; i < 8; i++) {
211  cmd[i + 2] = *matrix++;
212    }
213    drv_Sample_send(cmd, 10);
214}
215
216
217/* for graphic displays only */
218static void drv_Sample_blit(const int row, const int col, const int height, const int width)
219{
220    int r, c;
221
222    for (r = row; r < row + height; r++) {
223  for (c = col; c < col + width; c++) {
224      /* drv_generic_graphic_black() returns 1 if pixel is black */
225      /* drv_generic_graphic_gray() returns a gray value 0..255 */
226      /* drv_generic_graphic_rgb() returns a RGB color */
227      if (drv_generic_graphic_black(r, c)) {
228    /* set bit */
229      } else {
230    /* clear bit */
231      }
232  }
233    }
234}
235
236
237/* remove unless you have GPO's */
238static int drv_Sample_GPO(const int num, const int val)
239{
240    char cmd[4];
241
242    /* assume 0x42 to be the 'GPO' command */
243    cmd[0] = 0x42;
244    cmd[1] = num;
245    cmd[2] = (val > 0) ? 1 : 0;
246
247    drv_Sample_send(cmd, 3);
248
249    return 0;
250}
251
252
253/* example function used in a plugin */
254static int drv_Sample_contrast(int contrast)
255{
256    char cmd[2];
257
258    /* adjust limits according to the display */
259    if (contrast < 0)
260  contrast = 0;
261    if (contrast > 255)
262  contrast = 255;
263
264    /* call a 'contrast' function */
265    /* assume 0x04 to be the 'set contrast' command */
266    cmd[0] = 0x04;
267    cmd[1] = contrast;
268    drv_Sample_send(cmd, 2);
269
270    return contrast;
271}
272
273
274/* start text mode display */
275static int drv_Sample_start(const char *section)
276{
277    int contrast;
278    int rows = -1, cols = -1;
279    char *s;
280    char cmd[1];
281
282    s = cfg_get(section, "Size", NULL);
283    if (s == NULL || *s == '\0') {
284  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
285  return -1;
286    }
287    if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
288  error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
289  free(s);
290  return -1;
291    }
292
293    DROWS = rows;
294    DCOLS = cols;
295
296    /* number of GPO's; remove if you don't have them */
297    GPOS = 8;
298
299    /* open communication with the display */
300    if (drv_Sample_open(section) < 0) {
301  return -1;
302    }
303
304    /* reset & initialize display */
305    /* assume 0x00 to be a 'reset' command */
306    cmd[0] = 0x00;
307    drv_Sample_send(cmd, 0);
308
309    if (cfg_number(section, "Contrast", 0, 0, 255, &contrast) > 0) {
310  drv_Sample_contrast(contrast);
311    }
312
313    drv_Sample_clear();   /* clear display */
314
315    return 0;
316}
317
318
319/* start graphic display */
320static int drv_Sample_start2(const char *section)
321{
322    char *s;
323    char cmd[1];
324    int contrast;
325
326    /* read display size from config */
327    s = cfg_get(section, "Size", NULL);
328    if (s == NULL || *s == '\0') {
329  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
330  return -1;
331    }
332
333    DROWS = -1;
334    DCOLS = -1;
335    if (sscanf(s, "%dx%d", &DCOLS, &DROWS) != 2 || DCOLS < 1 || DROWS < 1) {
336  error("%s: bad Size '%s' from %s", Name, s, cfg_source());
337  return -1;
338    }
339
340    s = cfg_get(section, "Font", "6x8");
341    if (s == NULL || *s == '\0') {
342  error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
343  return -1;
344    }
345
346    XRES = -1;
347    YRES = -1;
348    if (sscanf(s, "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) {
349  error("%s: bad Font '%s' from %s", Name, s, cfg_source());
350  return -1;
351    }
352
353    /* Fixme: provider other fonts someday... */
354    if (XRES != 6 && YRES != 8) {
355  error("%s: bad Font '%s' from %s (only 6x8 at the moment)", Name, s, cfg_source());
356  return -1;
357    }
358
359    /* you surely want to allocate a framebuffer or something... */
360
361    /* open communication with the display */
362    if (drv_Sample_open(section) < 0) {
363  return -1;
364    }
365
366    /* reset & initialize display */
367    /* assume 0x00 to be a 'reset' command */
368    cmd[0] = 0x00;
369    drv_Sample_send(cmd, 1);
370
371    if (cfg_number(section, "Contrast", 0, 0, 255, &contrast) > 0) {
372  drv_Sample_contrast(contrast);
373    }
374
375    return 0;
376}
377
378
379/****************************************/
380/***            plugins               ***/
381/****************************************/
382
383static void plugin_contrast(RESULT * result, RESULT * arg1)
384{
385    double contrast;
386
387    contrast = drv_Sample_contrast(R2N(arg1));
388    SetResult(&result, R_NUMBER, &contrast);
389}
390
391
392/****************************************/
393/***        widget callbacks          ***/
394/****************************************/
395
396
397/* using drv_generic_text_draw(W) */
398/* using drv_generic_text_icon_draw(W) */
399/* using drv_generic_text_bar_draw(W) */
400/* using drv_generic_gpio_draw(W) */
401
402
403/****************************************/
404/***        exported functions        ***/
405/****************************************/
406
407
408/* list models */
409int drv_Sample_list(void)
410{
411    printf("generic");
412    return 0;
413}
414
415
416/* initialize driver & display */
417/* use this function for a text display */
418int drv_Sample_init(const char *section, const int quiet)
419{
420    WIDGET_CLASS wc;
421    int ret;
422
423    info("%s: %s", Name, "$Rev$");
424
425    /* display preferences */
426    XRES = 5;     /* pixel width of one char  */
427    YRES = 8;     /* pixel height of one char  */
428    CHARS = 8;      /* number of user-defineable characters */
429    CHAR0 = 0;      /* ASCII of first user-defineable char */
430    GOTO_COST = 2;    /* number of bytes a goto command requires */
431
432    /* real worker functions */
433    drv_generic_text_real_write = drv_Sample_write;
434    drv_generic_text_real_defchar = drv_Sample_defchar;
435
436    /* remove unless you have GPO's */
437    drv_generic_gpio_real_set = drv_Sample_GPO;
438
439
440    /* start display */
441    if ((ret = drv_Sample_start(section)) != 0)
442  return ret;
443
444    if (!quiet) {
445  char buffer[40];
446  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
447  if (drv_generic_text_greet(buffer, "www.bwct.de")) {
448      sleep(3);
449      drv_Sample_clear();
450  }
451    }
452
453    /* initialize generic text driver */
454    if ((ret = drv_generic_text_init(section, Name)) != 0)
455  return ret;
456
457    /* initialize generic icon driver */
458    if ((ret = drv_generic_text_icon_init()) != 0)
459  return ret;
460
461    /* initialize generic bar driver */
462    if ((ret = drv_generic_text_bar_init(0)) != 0)
463  return ret;
464
465    /* add fixed chars to the bar driver */
466    drv_generic_text_bar_add_segment(0, 0, 255, 32);  /* ASCII  32 = blank */
467
468
469    /* initialize generic GPIO driver */
470    /* remove unless you have GPO's */
471    if ((ret = drv_generic_gpio_init(section, Name)) != 0)
472  return ret;
473
474    /* register text widget */
475    wc = Widget_Text;
476    wc.draw = drv_generic_text_draw;
477    widget_register(&wc);
478
479    /* register icon widget */
480    wc = Widget_Icon;
481    wc.draw = drv_generic_text_icon_draw;
482    widget_register(&wc);
483
484    /* register bar widget */
485    wc = Widget_Bar;
486    wc.draw = drv_generic_text_bar_draw;
487    widget_register(&wc);
488
489    /* register plugins */
490    AddFunction("LCD::contrast", 1, plugin_contrast);
491
492    return 0;
493}
494
495
496/* initialize driver & display */
497/* use this function for a graphic display */
498int drv_Sample_init2(const char *section, const int quiet)
499{
500    int ret;
501
502    /* real worker functions */
503    drv_generic_graphic_real_blit = drv_Sample_blit;
504
505    /* remove unless you have GPO's */
506    drv_generic_gpio_real_set = drv_Sample_GPO;
507
508    /* start display */
509    if ((ret = drv_Sample_start2(section)) != 0)
510  return ret;
511
512    /* initialize generic graphic driver */
513    if ((ret = drv_generic_graphic_init(section, Name)) != 0)
514  return ret;
515
516    if (!quiet) {
517  char buffer[40];
518  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
519  if (drv_generic_graphic_greet(buffer, NULL)) {
520      sleep(3);
521      drv_generic_graphic_clear();
522  }
523    }
524
525    /* register plugins */
526    AddFunction("LCD::contrast", 1, plugin_contrast);
527
528    return 0;
529}
530
531
532
533/* close driver & display */
534/* use this function for a text display */
535int drv_Sample_quit(const int quiet)
536{
537
538    info("%s: shutting down.", Name);
539
540    drv_generic_text_quit();
541
542    /* remove unless you have GPO's */
543    drv_generic_gpio_quit();
544
545    /* clear display */
546    drv_Sample_clear();
547
548    /* say goodbye... */
549    if (!quiet) {
550  drv_generic_text_greet("goodbye!", NULL);
551    }
552
553    debug("closing connection");
554    drv_Sample_close();
555
556    return (0);
557}
558
559/* close driver & display */
560/* use this function for a graphic display */
561int drv_Sample_quit2(const int quiet)
562{
563
564    info("%s: shutting down.", Name);
565
566    /* clear display */
567    drv_generic_graphic_clear();
568
569    /* remove unless you have GPO's */
570    drv_generic_gpio_quit();
571
572    /* say goodbye... */
573    if (!quiet) {
574  drv_generic_graphic_greet("goodbye!", NULL);
575    }
576
577    drv_generic_graphic_quit();
578
579    debug("closing connection");
580    drv_Sample_close();
581
582    return (0);
583}
584
585
586/* use this one for a text display */
587DRIVER drv_Sample = {
588    .name = Name,
589    .list = drv_Sample_list,
590    .init = drv_Sample_init,
591    .quit = drv_Sample_quit,
592};
593
594
595/* use this one for a graphic display */
596DRIVER drv_Sample2 = {
597    .name = Name,
598    .list = drv_Sample_list,
599    .init = drv_Sample_init2,
600    .quit = drv_Sample_quit2,
601};
Note: See TracBrowser for help on using the browser.