~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_PICGraphic.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: drv_PICGraphic.c 1141 2011-01-23 17:01:08Z mzuther $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_PICGraphic.c $
 
3
 *
 
4
 * PICGraphic lcd4linux driver
 
5
 *
 
6
 * Copyright (C) 2009 Peter Bailey <peter.eldridge.bailey@gmail.com>
 
7
 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
 
8
 * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
9
 *
 
10
 * This file is part of LCD4Linux.
 
11
 *
 
12
 * LCD4Linux is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2, or (at your option)
 
15
 * any later version.
 
16
 *
 
17
 * LCD4Linux is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
25
 *
 
26
 */
 
27
 
 
28
/* 
 
29
 *
 
30
 * exported fuctions:
 
31
 *
 
32
 * struct DRIVER drv_PICGraphic
 
33
 *
 
34
 */
 
35
 
 
36
#include "config.h"
 
37
 
 
38
#include <stdlib.h>
 
39
#include <stdio.h>
 
40
#include <unistd.h>
 
41
#include <string.h>
 
42
#include <strings.h>
 
43
#include <errno.h>
 
44
 
 
45
#include "debug.h"
 
46
#include "cfg.h"
 
47
#include "qprintf.h"
 
48
#include "udelay.h"
 
49
#include "plugin.h"
 
50
#include "widget.h"
 
51
#include "widget_text.h"
 
52
#include "widget_icon.h"
 
53
#include "widget_bar.h"
 
54
#include "drv.h"
 
55
#include "timer.h"
 
56
 
 
57
#include "drv_generic_graphic.h"
 
58
#include "drv_generic_gpio.h"
 
59
#include "drv_generic_serial.h"
 
60
 
 
61
#define min(a,b) (a < b ? a : b)
 
62
 
 
63
static char Name[] = "PICGraphic";
 
64
 
 
65
//#define partialFrame
 
66
 
 
67
/* example config:
 
68
 
 
69
Display PICGraphic {
 
70
    Driver    'PICGraphic'
 
71
    Port      '/dev/ttyS1'
 
72
    Contrast  8
 
73
# these could be automatic
 
74
    Size      '48x128'
 
75
    Speed     115200
 
76
    Font      '6x8'
 
77
}
 
78
 
 
79
*/
 
80
 
 
81
/*
 
82
typedef struct {
 
83
    char *name;
 
84
    int columns;
 
85
    int rows;
 
86
    int max_contrast;
 
87
    int default_contrast;
 
88
    int gpo;
 
89
    int protocol;
 
90
} MODEL;
 
91
*/
 
92
 
 
93
static char *fbPG = 0, delayDone = 0;
 
94
 
 
95
void drv_PICGraphic_delay(void *arg)
 
96
{
 
97
    (void) arg;
 
98
    delayDone = 1;
 
99
    debug("delay done");
 
100
}
 
101
 
 
102
 
 
103
/****************************************/
 
104
/***  hardware-dependent functions    ***/
 
105
/****************************************/
 
106
static int drv_PICGraphic_open(const char *section)
 
107
{
 
108
    /* open serial port */
 
109
    if (drv_generic_serial_open(section, Name, 0) < 0)
 
110
        return -1;
 
111
 
 
112
    return 0;
 
113
}
 
114
 
 
115
 
 
116
static int drv_PICGraphic_close(void)
 
117
{
 
118
    /* close opened serial port */
 
119
    return drv_generic_serial_close();
 
120
}
 
121
 
 
122
static void convert2ASCII(char input, char *output)
 
123
{
 
124
    unsigned char temp = input >> 4;
 
125
    if (temp < 10)
 
126
        output[0] = temp + '0';
 
127
    else
 
128
        output[0] = temp - 10 + 'a';
 
129
    input &= 0xf;
 
130
    if (input < 10)
 
131
        output[1] = input + '0';
 
132
    else
 
133
        output[1] = input - 10 + 'a';
 
134
}
 
135
 
 
136
static void drv_PICGraphic_send(const char *data, const unsigned int len)
 
137
{
 
138
    unsigned int i;
 
139
    char hexDigits[3];
 
140
    hexDigits[2] = 0;
 
141
    drv_generic_serial_write(data, len);
 
142
    info("sending %d bytes: ", len);
 
143
    for (i = 0; i < min(10, len); i++) {        // min(10, len)
 
144
        convert2ASCII(data[i], hexDigits);
 
145
        debug("0x%s (%c)", hexDigits, data[i]);
 
146
    }
 
147
}
 
148
 
 
149
static int drv_PICGraphic_recv(char *dest, const unsigned int len, const char *expect)
 
150
{
 
151
    unsigned int bytes = 0;
 
152
    int status;
 
153
    while (bytes < len) {
 
154
        status = drv_generic_serial_read((char *) dest + bytes, 1);
 
155
        if (status == 1) {
 
156
            if (dest[bytes] != 0xa && dest[bytes] != 0xd) {
 
157
                if (dest[bytes] != '@') {
 
158
                    bytes += status;
 
159
                }
 
160
            }
 
161
        } else {
 
162
            info("error receiving response: %d", status);
 
163
            return status;
 
164
        }
 
165
        usleep(10000);
 
166
    }
 
167
    status = strncmp((const char *) dest, expect, len);
 
168
    if (!status) {
 
169
        return 0;
 
170
    } else {
 
171
        return 1;
 
172
    }
 
173
 
 
174
}
 
175
 
 
176
static void drv_PICGraphic_blit(const int row, const int col, const int height, const int width)
 
177
{
 
178
    /* update a rectangular portion of the display */
 
179
    int r, c, index, status;
 
180
    unsigned char cmd[5];
 
181
 
 
182
    debug("blit from (%d,%d) to (%d,%d) out of (%d,%d)", row, col, row + height, col + width, DROWS, DCOLS);
 
183
    if (!fbPG)
 
184
        return;
 
185
    for (c = min(col, DCOLS - 1); c < min(col + width, DCOLS); c++) {
 
186
        for (r = min(row, DROWS - 1); r < min(row + height, DROWS); r++) {
 
187
            index = DCOLS * (r / 8) + c;
 
188
            if (index < 0 || index >= DCOLS * DROWS / 8) {
 
189
                error("index too large: %d, r: %d, c: %d", index, r, c);
 
190
                break;
 
191
            }
 
192
            if (drv_generic_graphic_black(r, c)) {
 
193
                fbPG[index] |= (1 << (r % 8));
 
194
            } else {
 
195
                fbPG[index] &= ~(1 << (r % 8));
 
196
            }
 
197
        }
 
198
    }
 
199
 
 
200
    // send rectangular portion with height divisible by 8
 
201
#ifdef partialFrame
 
202
    if (delayDone) {
 
203
        delayDone = 0;
 
204
        int row8, height8;
 
205
        row8 = 8 * (row / 8);
 
206
        height8 = 8 * (height / 8) + !!(height % 8);
 
207
        info("sending blit");
 
208
        cmd[0] = 'b';
 
209
        cmd[1] = row8;
 
210
        cmd[2] = col;
 
211
        cmd[3] = height8;
 
212
        cmd[4] = width;
 
213
        drv_PICGraphic_send(cmd, 5);
 
214
        for (r = min(row8, DROWS - 1); r < min(row8 + height8, DROWS); r += 8) {
 
215
            drv_PICGraphic_send(fbPG + DCOLS * (r / 8) + col, width);
 
216
        }
 
217
    }
 
218
#else
 
219
    // send full frame
 
220
    if (delayDone) {
 
221
        delayDone = 0;
 
222
        info("sending frame");
 
223
        cmd[0] = 'f';
 
224
        drv_PICGraphic_send((char *) cmd, 1);
 
225
        drv_PICGraphic_send(fbPG, DROWS * DCOLS / 8);
 
226
        usleep(20000);
 
227
        // wait for reception of confirmation code
 
228
        status = drv_PICGraphic_recv((char *) cmd, 2, "ff");
 
229
        if (!status) {
 
230
            info("received ff from device");
 
231
        } else {
 
232
            info("did not receive ff from device");
 
233
        }
 
234
 
 
235
    }
 
236
#endif
 
237
}
 
238
 
 
239
static int drv_PICGraphic_GPO(const int num, const int val)
 
240
{
 
241
    char cmd[3];
 
242
 
 
243
    cmd[0] = 'g';
 
244
    cmd[1] = val ? 's' : 'c';
 
245
    cmd[2] = num;
 
246
 
 
247
    // todo: fixme
 
248
//    drv_PICGraphic_send(cmd, 3);
 
249
 
 
250
    return 0;
 
251
}
 
252
 
 
253
static int drv_PICGraphic_GPI(const int num)
 
254
{
 
255
    char cmd[3];
 
256
    int ret = 0;
 
257
 
 
258
    cmd[0] = 'g';
 
259
    cmd[1] = 'r';
 
260
    cmd[2] = num;
 
261
 
 
262
    // todo: fixme
 
263
//    drv_PICGraphic_send(cmd, 3);
 
264
//    ret = drv_generic_serial_read(cmd, 1);
 
265
 
 
266
    if (ret)
 
267
        return -1;
 
268
    else
 
269
        return cmd[0];
 
270
}
 
271
 
 
272
/* example function used in a plugin */
 
273
static int drv_PICGraphic_contrast(int contrast)
 
274
{
 
275
    char cmd[2];
 
276
 
 
277
    /* adjust limits according to the display */
 
278
    if (contrast < 0)
 
279
        contrast = 0;
 
280
    if (contrast > 15)
 
281
        contrast = 15;
 
282
 
 
283
    /* call a 'contrast' function */
 
284
    cmd[0] = 'c';
 
285
    cmd[1] = contrast;
 
286
    // todo: fixme
 
287
//    drv_PICGraphic_send(cmd, 2);
 
288
 
 
289
    return contrast;
 
290
}
 
291
 
 
292
/* start graphic display */
 
293
static int drv_PICGraphic_start2(const char *section)
 
294
{
 
295
    char *s;
 
296
    char cmd[2];
 
297
    int contrast, status, tick, tack;
 
298
 
 
299
    /* read display size from config */
 
300
    s = cfg_get(section, "Size", NULL);
 
301
    if (s == NULL || *s == '\0') {
 
302
        error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
 
303
        return -1;
 
304
    }
 
305
 
 
306
    DROWS = -1;
 
307
    DCOLS = -1;
 
308
    if (sscanf(s, "%dx%d", &DCOLS, &DROWS) != 2 || DCOLS < 1 || DROWS < 1) {
 
309
        error("%s: bad Size '%s' from %s", Name, s, cfg_source());
 
310
        return -1;
 
311
    }
 
312
 
 
313
    s = cfg_get(section, "Font", "6x8");
 
314
    if (s == NULL || *s == '\0') {
 
315
        error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
 
316
        return -1;
 
317
    }
 
318
 
 
319
    XRES = -1;
 
320
    YRES = -1;
 
321
    if (sscanf(s, "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) {
 
322
        error("%s: bad Font '%s' from %s", Name, s, cfg_source());
 
323
        return -1;
 
324
    }
 
325
 
 
326
    if (XRES != 6 && YRES != 8) {
 
327
        error("%s: bad Font '%s' from %s (only 6x8 at the moment)", Name, s, cfg_source());
 
328
        return -1;
 
329
    }
 
330
 
 
331
    /* you surely want to allocate a framebuffer or something... */
 
332
    fbPG = calloc(DCOLS * DROWS / 8, 1);
 
333
    if (!fbPG) {
 
334
        error("failed to allocate framebuffer");
 
335
        return -1;
 
336
    }
 
337
 
 
338
    info("allocated framebuffer with size %d", DCOLS * DROWS / 8);
 
339
    if (cfg_number("Variables", "tick", 500, 100, 0, &tick) > 0 &&
 
340
        cfg_number("Variables", "tack", 500, 100, 0, &tack) > 0) {
 
341
        info("tick & tack read from config");
 
342
        timer_add(drv_PICGraphic_delay, 0, min(tick, tack), 0); // 
 
343
    } else {
 
344
        info("tick & tack not read from config");
 
345
        timer_add(drv_PICGraphic_delay, 0, 80, 0);      // 
 
346
    }
 
347
 
 
348
    /* open communication with the display */
 
349
    if (drv_PICGraphic_open(section) < 0) {
 
350
        return -1;
 
351
    }
 
352
 
 
353
    /* reset & initialize display */
 
354
    cmd[0] = 'i';
 
355
    drv_PICGraphic_send(cmd, 1);
 
356
    usleep(10000);
 
357
    // wait for reception of confirmation code
 
358
    status = drv_PICGraphic_recv(cmd, 2, "fi");
 
359
 
 
360
    if (!status) {
 
361
        info("received fi from device");
 
362
    } else {
 
363
        info("did not receive fi from device");
 
364
    }
 
365
 
 
366
    if (cfg_number(section, "Contrast", 8, 0, 15, &contrast) > 0) {
 
367
        drv_PICGraphic_contrast(contrast);
 
368
    }
 
369
 
 
370
    return 0;
 
371
}
 
372
 
 
373
 
 
374
/****************************************/
 
375
/***            plugins               ***/
 
376
/****************************************/
 
377
 
 
378
static void plugin_contrast(RESULT * result, RESULT * arg1)
 
379
{
 
380
    double contrast;
 
381
 
 
382
    contrast = drv_PICGraphic_contrast(R2N(arg1));
 
383
    SetResult(&result, R_NUMBER, &contrast);
 
384
}
 
385
 
 
386
 
 
387
/****************************************/
 
388
/***        widget callbacks          ***/
 
389
/****************************************/
 
390
 
 
391
 
 
392
/* using drv_generic_text_draw(W) */
 
393
/* using drv_generic_text_icon_draw(W) */
 
394
/* using drv_generic_text_bar_draw(W) */
 
395
/* using drv_generic_gpio_draw(W) */
 
396
 
 
397
 
 
398
/****************************************/
 
399
/***        exported functions        ***/
 
400
/****************************************/
 
401
 
 
402
 
 
403
/* list models */
 
404
int drv_PICGraphic_list(void)
 
405
{
 
406
    printf("PICGraphic serial-to-graphic by Peter Bailey");
 
407
    return 0;
 
408
}
 
409
 
 
410
/* initialize driver & display */
 
411
int drv_PICGraphic_init2(const char *section, const int quiet)
 
412
{
 
413
    int ret;
 
414
 
 
415
    /* real worker functions */
 
416
    drv_generic_graphic_real_blit = drv_PICGraphic_blit;
 
417
    drv_generic_gpio_real_set = drv_PICGraphic_GPO;
 
418
    drv_generic_gpio_real_get = drv_PICGraphic_GPI;
 
419
 
 
420
    /* start display */
 
421
    if ((ret = drv_PICGraphic_start2(section)) != 0)
 
422
        return ret;
 
423
 
 
424
    /* initialize generic graphic driver */
 
425
    if ((ret = drv_generic_graphic_init(section, Name)) != 0)
 
426
        return ret;
 
427
 
 
428
    if (!quiet) {
 
429
        char buffer[40];
 
430
        qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
 
431
        if (drv_generic_graphic_greet(buffer, NULL)) {
 
432
            sleep(3);
 
433
            drv_generic_graphic_clear();        // also clears main framebuffer
 
434
        }
 
435
    }
 
436
 
 
437
    /* register plugins */
 
438
    AddFunction("LCD::contrast", 1, plugin_contrast);
 
439
 
 
440
    return 0;
 
441
}
 
442
 
 
443
/* close driver & display */
 
444
/* use this function for a graphic display */
 
445
int drv_PICGraphic_quit2(const int quiet)
 
446
{
 
447
 
 
448
    info("%s: shutting down.", Name);
 
449
 
 
450
    /* clear display */
 
451
    drv_generic_graphic_clear();
 
452
 
 
453
    drv_generic_gpio_quit();
 
454
 
 
455
 
 
456
    /* say goodbye... */
 
457
    if (!quiet) {
 
458
        drv_generic_graphic_greet("goodbye!", NULL);
 
459
    }
 
460
 
 
461
    info("freeing framebuffer");
 
462
    free(fbPG);
 
463
 
 
464
    drv_generic_graphic_quit();
 
465
 
 
466
    debug("closing connection");
 
467
    drv_PICGraphic_close();
 
468
 
 
469
    return (0);
 
470
}
 
471
 
 
472
/* use this one for a graphic display */
 
473
DRIVER drv_PICGraphic = {
 
474
    .name = Name,
 
475
    .list = drv_PICGraphic_list,
 
476
    .init = drv_PICGraphic_init2,
 
477
    .quit = drv_PICGraphic_quit2,
 
478
};