3 @@ -39,7 +39,7 @@ AC_ARG_WITH(
4 [ Newhaven, Noritake, NULL, Pertelian, PHAnderson,]
5 [ PICGraphic, picoLCD, picoLCDGraphic, PNG, PPM, RouterBoard,]
6 [ Sample, SamsungSPF, serdisplib, ShuttleVFD, SimpleLCD, st2205, T6963,]
7 - [ TeakLCM, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
8 + [ TeakLCM, TEW673GRU, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
12 @@ -107,6 +107,7 @@ for driver in $drivers; do
20 @@ -260,6 +261,9 @@ for driver in $drivers; do
30 @@ -800,6 +804,18 @@ if test "$TeakLCM" = "yes"; then
31 AC_DEFINE(WITH_TEAK_LCM,1,[TeakLCM driver])
34 +if test "$TEW673GRU" = "yes"; then
35 + if test "$has_spidev" = "true"; then
39 + DRIVERS="$DRIVERS drv_TEW673GRU.o"
40 + AC_DEFINE(WITH_TEW673GRU,1,[TEW673GRU driver])
42 + AC_MSG_WARN(linux/spi/spidev.h not found: TEW673GRU driver disabled)
46 if test "$Trefon" = "yes"; then
47 if test "$has_usb" = "true"; then
51 @@ -92,6 +92,7 @@ extern DRIVER drv_serdisplib;
52 extern DRIVER drv_ShuttleVFD;
53 extern DRIVER drv_SimpleLCD;
54 extern DRIVER drv_T6963;
55 +extern DRIVER drv_TEW673GRU;
56 extern DRIVER drv_TeakLCM;
57 extern DRIVER drv_Trefon;
58 extern DRIVER drv_ula200;
59 @@ -248,6 +249,9 @@ DRIVER *Driver[] = {
63 +#ifdef WITH_TEW673GRU
71 @@ -117,6 +117,7 @@ drv_ShuttleVFD.c \
85 + * TRENDnet TEW673GRU LCD4linux driver
87 + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
89 + * based on the Sample driver which is:
90 + * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
91 + * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
93 + * This file is part of LCD4Linux.
95 + * LCD4Linux is free software; you can redistribute it and/or modify
96 + * it under the terms of the GNU General Public License as published by
97 + * the Free Software Foundation; either version 2, or (at your option)
98 + * any later version.
100 + * LCD4Linux is distributed in the hope that it will be useful,
101 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
102 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103 + * GNU General Public License for more details.
105 + * You should have received a copy of the GNU General Public License
106 + * along with this program; if not, write to the Free Software
107 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
112 + * exported fuctions:
114 + * struct DRIVER drv_TEW673GRU
127 +#include "qprintf.h"
131 +#include "widget_text.h"
132 +#include "widget_icon.h"
133 +#include "widget_bar.h"
136 +#include "drv_generic_text.h"
137 +#include "drv_generic_graphic.h"
138 +#include "drv_generic_spidev.h"
141 +#include <dmalloc.h>
144 +#define TEW673GRU_NUM_COLS 220
145 +#define TEW673GRU_NUM_ROWS 176
146 +#define TEW673GRU_BPP 2 /* bytes per pixel */
148 +#define TEW673GRU_CMD_SIZE 9
149 +#define TEW673GRU_NUM_ROW_BYTES (TEW673GRU_NUM_COLS * TEW673GRU_BPP)
152 + CMD_SHOW_STRING = 49,
153 + CMD_SHOW_IMAGE_DIR = 52,
154 + CMD_SCREEN_COLOR = 54,
157 +static char Name[] = "TEW673GRU";
159 +static char *drv_TEW673GRU_FB;
160 +static long FB_SIZE;
163 +static unsigned int RGBAto16(RGBA rgb)
165 + return (((rgb.R >> 3) << 11) | ((rgb.G >> 2) << 5) | (rgb.B >> 3));
168 +static unsigned char color_msb(unsigned int color)
173 +static unsigned char color_lsb(unsigned int color)
175 + return color & 0xff;
178 +static void drv_TEW673GRU_hw_clear(const unsigned int color)
180 + unsigned char cmd[TEW673GRU_CMD_SIZE];
181 + struct spi_ioc_transfer tr[1];
183 + memset(tr, '\0', sizeof(tr));
184 + memset(cmd, '\0', sizeof(cmd));
186 + cmd[0] = CMD_SCREEN_COLOR;
187 + cmd[7] = color_msb(color);
188 + cmd[8] = color_lsb(color);
190 + tr[0].tx_buf = (unsigned long) cmd;
191 + tr[0].len = sizeof(cmd);
193 + drv_generic_spidev_transfer(1, tr);
196 +static void drv_TEW673GRU_hw_send_row(const int row, const int col, const char *data, const int width)
198 + unsigned char cmd[TEW673GRU_CMD_SIZE];
199 + struct spi_ioc_transfer tr[2];
202 + memset(tr, '\0', sizeof(tr));
203 + memset(cmd, '\0', sizeof(cmd));
205 + datasize = width * TEW673GRU_BPP;
207 + cmd[0] = CMD_SHOW_IMAGE_DIR;
209 + cmd[2] = col + width;
212 + cmd[5] = datasize >> 8;
213 + cmd[6] = datasize & 0xff;
215 + tr[0].tx_buf = (unsigned long) cmd;
216 + tr[0].len = sizeof(cmd);
217 + tr[1].tx_buf = (unsigned long) data;
218 + tr[1].len = datasize;
220 + drv_generic_spidev_transfer(2, tr);
223 +static void drv_TEW673GRU_hw_write_string(const int row, const int col, const char *data, const int datasize)
225 + unsigned char cmd[TEW673GRU_CMD_SIZE];
226 + struct spi_ioc_transfer tr[2];
229 + memset(tr, '\0', sizeof(tr));
230 + memset(cmd, '\0', sizeof(cmd));
232 + len = datasize & 0xff;
233 + cmd[0] = CMD_SHOW_STRING;
235 + cmd[2] = col + (XRES * len);
237 + cmd[4] = row + YRES;
241 + tr[0].tx_buf = (unsigned long) cmd;
242 + tr[0].len = sizeof(cmd);
243 + tr[1].tx_buf = (unsigned long) data;
244 + tr[1].len = datasize;
246 + drv_generic_spidev_transfer(2, tr);
249 +static void drv_TEW673GRU_FB_set_pixel(const int col, const unsigned int color)
253 + pos = col * TEW673GRU_BPP;
254 + drv_TEW673GRU_FB[pos] = color_msb(color);
255 + drv_TEW673GRU_FB[pos + 1] = color_lsb(color);
258 +static void drv_TEW673GRU_blit(const int row, const int col, const int height, const int width)
262 + debug("%s: update area r:%d c:%d w:%d h:%d", Name, row, col, height, width);
264 + for (r = row; r < row + height; r++) {
265 + for (c = col; c < col + width; c++) {
266 + unsigned int color;
269 + rgb = drv_generic_graphic_rgb(r, c);
270 + color = RGBAto16(rgb);
271 + drv_TEW673GRU_FB_set_pixel(c, color);
277 + data = &drv_TEW673GRU_FB[col * TEW673GRU_BPP];
278 + drv_TEW673GRU_hw_send_row(r, col, data, width);
279 + udelay(100 + width * 50);
284 +static void drv_TEW673GRU_clear(RGBA rgba)
286 + unsigned int color;
288 + color = RGBAto16(rgba);
289 + drv_TEW673GRU_hw_clear(color);
292 +static void drv_TEW673GRU_write(const int row, const int col, const char *data, const int len)
296 + for (i = 0; i < len; i++) {
297 + drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, " ", 1);
299 + drv_TEW673GRU_hw_write_string(row * YRES, 2 + (col + i) * XRES, " ", 1);
301 + drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, &data[i], 1);
306 +static int drv_TEW673GRU_open(const char *section)
310 + err = drv_generic_spidev_open(section, Name);
317 +static int drv_TEW673GRU_close(void)
319 + drv_generic_spidev_close();
323 +static void drv_TEW673GRU_clear_screen(void)
326 + drv_generic_graphic_clear();
328 + memset(drv_TEW673GRU_FB, ' ', FB_SIZE);
329 + drv_TEW673GRU_hw_clear(0x0000);
333 +static int drv_TEW673GRU_init_font(const char *section)
338 + font = cfg_get(section, "Font", "6x8");
339 + if (font == NULL) {
340 + error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
344 + if (*font == '\0') {
345 + error("%s: invalid '%s.Font' entry in %s", Name, section, cfg_source());
351 + if (sscanf(font, "%dx%d", &XRES, &YRES) != 2 ||
354 + error("%s: bad Font '%s' from %s", Name, font, cfg_source());
358 + if (XRES != 6 && YRES != 8) {
359 + error("%s: bad Font '%s' from %s (only 6x8 at the moment)",
360 + Name, font, cfg_source());
364 + error("%s: font '%s' selected", Name, font);
374 +static int drv_TEW673GRU_start(const char *section)
378 + DCOLS = TEW673GRU_NUM_COLS;
379 + DROWS = TEW673GRU_NUM_ROWS;
382 + ret = drv_TEW673GRU_init_font(section);
386 + FB_SIZE = DCOLS * TEW673GRU_BPP;
390 + DCOLS = DCOLS / XRES;
391 + DROWS = DROWS / YRES;
393 + FB_SIZE = DCOLS * DROWS;
397 + drv_TEW673GRU_FB = malloc(FB_SIZE);
398 + if (drv_TEW673GRU_FB == NULL) {
399 + error("%s: framebuffer could not be allocated", Name);
404 + ret = drv_TEW673GRU_open(section);
409 + drv_TEW673GRU_clear_screen();
414 + if (drv_TEW673GRU_FB)
415 + free(drv_TEW673GRU_FB);
420 +static int drv_TEW673GRU_greet(const char *msg1, const char *msg2)
423 + return drv_generic_graphic_greet(msg1, msg2);
425 + return drv_generic_text_greet(msg1, msg2);
429 +/****************************************/
430 +/*** widget callbacks ***/
431 +/****************************************/
434 +/* using drv_generic_text_draw(W) */
435 +/* using drv_generic_text_icon_draw(W) */
436 +/* using drv_generic_text_bar_draw(W) */
437 +/* using drv_generic_gpio_draw(W) */
440 +/****************************************/
441 +/*** exported functions ***/
442 +/****************************************/
444 +int drv_TEW673GRU_list(void)
446 + printf("TEW673GRU driver");
450 +int drv_TEW673GRU_init(const char *section, const int quiet)
455 + cfg_number(section, "Mode", 0, 0, 1, &MODE);
458 + drv_generic_graphic_real_blit = drv_TEW673GRU_blit;
459 + drv_generic_graphic_real_clear = drv_TEW673GRU_clear;
461 + drv_generic_text_real_write = drv_TEW673GRU_write;
464 + ret = drv_TEW673GRU_start(section);
469 + ret = drv_generic_graphic_init(section, Name);
473 + ret = drv_generic_text_init(section, Name);
477 + ret = drv_generic_text_icon_init();
481 + ret = drv_generic_text_bar_init(1);
485 + drv_generic_text_bar_add_segment(0, 0, 255, ' ');
486 + drv_generic_text_bar_add_segment(255, 255, 255, '#');
489 + wc.draw = drv_generic_text_draw;
490 + widget_register(&wc);
493 + wc.draw = drv_generic_text_icon_draw;
494 + widget_register(&wc);
497 + wc.draw = drv_generic_text_bar_draw;
498 + widget_register(&wc);
503 + qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
504 + drv_TEW673GRU_greet(buffer, "www.openwrt.org");
506 + drv_TEW673GRU_clear_screen();
512 +int drv_TEW673GRU_quit(const int quiet)
515 + info("%s: shutting down.", Name);
517 + drv_TEW673GRU_clear_screen();
520 + drv_TEW673GRU_greet("goodbye!", NULL);
523 + drv_generic_graphic_quit();
525 + drv_generic_text_quit();
527 + debug("closing connection");
528 + drv_TEW673GRU_close();
533 +DRIVER drv_TEW673GRU = {
535 + .list = drv_TEW673GRU_list,
536 + .init = drv_TEW673GRU_init,
537 + .quit = drv_TEW673GRU_quit,
539 --- a/lcd4linux.conf.sample
540 +++ b/lcd4linux.conf.sample
541 @@ -571,6 +571,11 @@ Display FutabaVFD {
548 + Port '/dev/spidev1.0'