You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

552 lines
13 KiB

  1. --- a/drivers.m4
  2. +++ b/drivers.m4
  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],
  9. drivers=$withval,
  10. drivers=all
  11. )
  12. @@ -107,6 +107,7 @@ for driver in $drivers; do
  13. SHUTTLEVFD="yes"
  14. SIMPLELCD="yes"
  15. T6963="yes"
  16. + TEW673GRU="yes"
  17. TeakLCM="yes"
  18. Trefon="yes"
  19. ULA200="yes"
  20. @@ -260,6 +261,9 @@ for driver in $drivers; do
  21. TeakLCM)
  22. TeakLCM=$val
  23. ;;
  24. + TEW673GRU)
  25. + TEW673GRU=$val
  26. + ;;
  27. Trefon)
  28. Trefon=$val
  29. ;;
  30. @@ -797,6 +801,18 @@ if test "$TeakLCM" = "yes"; then
  31. AC_DEFINE(WITH_TEAK_LCM,1,[TeakLCM driver])
  32. fi
  33. +if test "$TEW673GRU" = "yes"; then
  34. + if test "$has_spidev" = "true"; then
  35. + GRAPHIC="yes"
  36. + TEXT="yes"
  37. + SPIDEV="yes"
  38. + DRIVERS="$DRIVERS drv_TEW673GRU.o"
  39. + AC_DEFINE(WITH_TEW673GRU,1,[TEW673GRU driver])
  40. + else
  41. + AC_MSG_WARN(linux/spi/spidev.h not found: TEW673GRU driver disabled)
  42. + fi
  43. +fi
  44. +
  45. if test "$Trefon" = "yes"; then
  46. if test "$has_usb" = "true"; then
  47. TEXT="yes"
  48. --- a/drv.c
  49. +++ b/drv.c
  50. @@ -92,6 +92,7 @@ extern DRIVER drv_serdisplib;
  51. extern DRIVER drv_ShuttleVFD;
  52. extern DRIVER drv_SimpleLCD;
  53. extern DRIVER drv_T6963;
  54. +extern DRIVER drv_TEW673GRU;
  55. extern DRIVER drv_TeakLCM;
  56. extern DRIVER drv_Trefon;
  57. extern DRIVER drv_ula200;
  58. @@ -248,6 +249,9 @@ DRIVER *Driver[] = {
  59. #ifdef WITH_TEAK_LCM
  60. &drv_TeakLCM,
  61. #endif
  62. +#ifdef WITH_TEW673GRU
  63. + &drv_TEW673GRU,
  64. +#endif
  65. #ifdef WITH_TREFON
  66. &drv_Trefon,
  67. #endif
  68. --- a/Makefile.am
  69. +++ b/Makefile.am
  70. @@ -120,6 +120,7 @@ drv_ShuttleVFD.c \
  71. drv_SimpleLCD.c \
  72. drv_T6963.c \
  73. drv_TeakLCM.c \
  74. +drv_TEW673GRU.c \
  75. drv_Trefon.c \
  76. drv_ula200.c \
  77. drv_USBHUB.c \
  78. --- /dev/null
  79. +++ b/drv_TEW673GRU.c
  80. @@ -0,0 +1,457 @@
  81. +/* $Id$
  82. + * $URL$
  83. + *
  84. + * TRENDnet TEW673GRU LCD4linux driver
  85. + *
  86. + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
  87. + *
  88. + * based on the Sample driver which is:
  89. + * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
  90. + * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
  91. + *
  92. + * This file is part of LCD4Linux.
  93. + *
  94. + * LCD4Linux is free software; you can redistribute it and/or modify
  95. + * it under the terms of the GNU General Public License as published by
  96. + * the Free Software Foundation; either version 2, or (at your option)
  97. + * any later version.
  98. + *
  99. + * LCD4Linux is distributed in the hope that it will be useful,
  100. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  101. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  102. + * GNU General Public License for more details.
  103. + *
  104. + * You should have received a copy of the GNU General Public License
  105. + * along with this program; if not, write to the Free Software
  106. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  107. + *
  108. + */
  109. +
  110. +/*
  111. + * exported fuctions:
  112. + *
  113. + * struct DRIVER drv_TEW673GRU
  114. + */
  115. +
  116. +#include "config.h"
  117. +
  118. +#include <stdlib.h>
  119. +#include <stdio.h>
  120. +#include <unistd.h>
  121. +#include <string.h>
  122. +#include <errno.h>
  123. +
  124. +#include "debug.h"
  125. +#include "cfg.h"
  126. +#include "qprintf.h"
  127. +#include "udelay.h"
  128. +#include "plugin.h"
  129. +#include "widget.h"
  130. +#include "widget_text.h"
  131. +#include "widget_icon.h"
  132. +#include "widget_bar.h"
  133. +#include "drv.h"
  134. +
  135. +#include "drv_generic_text.h"
  136. +#include "drv_generic_graphic.h"
  137. +#include "drv_generic_spidev.h"
  138. +
  139. +#ifdef WITH_DMALLOC
  140. +#include <dmalloc.h>
  141. +#endif
  142. +
  143. +#define TEW673GRU_NUM_COLS 220
  144. +#define TEW673GRU_NUM_ROWS 176
  145. +#define TEW673GRU_BPP 2 /* bytes per pixel */
  146. +
  147. +#define TEW673GRU_CMD_SIZE 9
  148. +#define TEW673GRU_NUM_ROW_BYTES (TEW673GRU_NUM_COLS * TEW673GRU_BPP)
  149. +
  150. +enum {
  151. + CMD_SHOW_STRING = 49,
  152. + CMD_SHOW_IMAGE_DIR = 52,
  153. + CMD_SCREEN_COLOR = 54,
  154. +};
  155. +
  156. +static char Name[] = "TEW673GRU";
  157. +
  158. +static char *drv_TEW673GRU_FB;
  159. +static long FB_SIZE;
  160. +static int MODE;
  161. +
  162. +static unsigned int RGBAto16(RGBA rgb)
  163. +{
  164. + return (((rgb.R >> 3) << 11) | ((rgb.G >> 2) << 5) | (rgb.B >> 3));
  165. +}
  166. +
  167. +static unsigned char color_msb(unsigned int color)
  168. +{
  169. + return color >> 8;
  170. +}
  171. +
  172. +static unsigned char color_lsb(unsigned int color)
  173. +{
  174. + return color & 0xff;
  175. +}
  176. +
  177. +static void drv_TEW673GRU_hw_clear(const unsigned int color)
  178. +{
  179. + unsigned char cmd[TEW673GRU_CMD_SIZE];
  180. + struct spi_ioc_transfer tr[1];
  181. +
  182. + memset(tr, '\0', sizeof(tr));
  183. + memset(cmd, '\0', sizeof(cmd));
  184. +
  185. + cmd[0] = CMD_SCREEN_COLOR;
  186. + cmd[7] = color_msb(color);
  187. + cmd[8] = color_lsb(color);
  188. +
  189. + tr[0].tx_buf = (unsigned long) cmd;
  190. + tr[0].len = sizeof(cmd);
  191. +
  192. + drv_generic_spidev_transfer(1, tr);
  193. +}
  194. +
  195. +static void drv_TEW673GRU_hw_send_row(const int row, const int col, const char *data, const int width)
  196. +{
  197. + unsigned char cmd[TEW673GRU_CMD_SIZE];
  198. + struct spi_ioc_transfer tr[2];
  199. + int datasize;
  200. +
  201. + memset(tr, '\0', sizeof(tr));
  202. + memset(cmd, '\0', sizeof(cmd));
  203. +
  204. + datasize = width * TEW673GRU_BPP;
  205. +
  206. + cmd[0] = CMD_SHOW_IMAGE_DIR;
  207. + cmd[1] = col;
  208. + cmd[2] = col + width;
  209. + cmd[3] = row;
  210. + cmd[4] = row;
  211. + cmd[5] = datasize >> 8;
  212. + cmd[6] = datasize & 0xff;
  213. +
  214. + tr[0].tx_buf = (unsigned long) cmd;
  215. + tr[0].len = sizeof(cmd);
  216. + tr[1].tx_buf = (unsigned long) data;
  217. + tr[1].len = datasize;
  218. +
  219. + drv_generic_spidev_transfer(2, tr);
  220. +}
  221. +
  222. +static void drv_TEW673GRU_hw_write_string(const int row, const int col, const char *data, const int datasize)
  223. +{
  224. + unsigned char cmd[TEW673GRU_CMD_SIZE];
  225. + struct spi_ioc_transfer tr[2];
  226. + unsigned char len;
  227. +
  228. + memset(tr, '\0', sizeof(tr));
  229. + memset(cmd, '\0', sizeof(cmd));
  230. +
  231. + len = datasize & 0xff;
  232. + cmd[0] = CMD_SHOW_STRING;
  233. + cmd[1] = col;
  234. + cmd[2] = col + (XRES * len);
  235. + cmd[3] = row;
  236. + cmd[4] = row + YRES;
  237. + cmd[7] = 0;
  238. + cmd[8] = len;
  239. +
  240. + tr[0].tx_buf = (unsigned long) cmd;
  241. + tr[0].len = sizeof(cmd);
  242. + tr[1].tx_buf = (unsigned long) data;
  243. + tr[1].len = datasize;
  244. +
  245. + drv_generic_spidev_transfer(2, tr);
  246. +}
  247. +
  248. +static void drv_TEW673GRU_FB_set_pixel(const int col, const unsigned int color)
  249. +{
  250. + int pos;
  251. +
  252. + pos = col * TEW673GRU_BPP;
  253. + drv_TEW673GRU_FB[pos] = color_msb(color);
  254. + drv_TEW673GRU_FB[pos + 1] = color_lsb(color);
  255. +}
  256. +
  257. +static void drv_TEW673GRU_blit(const int row, const int col, const int height, const int width)
  258. +{
  259. + int r, c;
  260. +
  261. + debug("%s: update area r:%d c:%d w:%d h:%d", Name, row, col, height, width);
  262. +
  263. + for (r = row; r < row + height; r++) {
  264. + for (c = col; c < col + width; c++) {
  265. + unsigned int color;
  266. + RGBA rgb;
  267. +
  268. + rgb = drv_generic_graphic_rgb(r, c);
  269. + color = RGBAto16(rgb);
  270. + drv_TEW673GRU_FB_set_pixel(c, color);
  271. + }
  272. +
  273. + if (width) {
  274. + char *data;
  275. +
  276. + data = &drv_TEW673GRU_FB[col * TEW673GRU_BPP];
  277. + drv_TEW673GRU_hw_send_row(r, col, data, width);
  278. + udelay(100 + width * 50);
  279. + }
  280. + }
  281. +}
  282. +
  283. +static void drv_TEW673GRU_clear(RGBA rgba)
  284. +{
  285. + unsigned int color;
  286. +
  287. + color = RGBAto16(rgba);
  288. + drv_TEW673GRU_hw_clear(color);
  289. +}
  290. +
  291. +static void drv_TEW673GRU_write(const int row, const int col, const char *data, const int len)
  292. +{
  293. + int i;
  294. +
  295. + for (i = 0; i < len; i++) {
  296. + drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, " ", 1);
  297. + udelay(10000);
  298. + drv_TEW673GRU_hw_write_string(row * YRES, 2 + (col + i) * XRES, " ", 1);
  299. + udelay(10000);
  300. + drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, &data[i], 1);
  301. + udelay(10000);
  302. + }
  303. +}
  304. +
  305. +static int drv_TEW673GRU_open(const char *section)
  306. +{
  307. + int err;
  308. +
  309. + err = drv_generic_spidev_open(section, Name);
  310. + if (err < 0)
  311. + return err;
  312. +
  313. + return 0;
  314. +}
  315. +
  316. +static int drv_TEW673GRU_close(void)
  317. +{
  318. + drv_generic_spidev_close();
  319. + return 0;
  320. +}
  321. +
  322. +static void drv_TEW673GRU_clear_screen(void)
  323. +{
  324. + if (MODE) {
  325. + drv_generic_graphic_clear();
  326. + } else {
  327. + memset(drv_TEW673GRU_FB, ' ', FB_SIZE);
  328. + drv_TEW673GRU_hw_clear(0x0000);
  329. + }
  330. +}
  331. +
  332. +static int drv_TEW673GRU_init_font(const char *section)
  333. +{
  334. + char *font;
  335. + int ret = -1;
  336. +
  337. + font = cfg_get(section, "Font", "6x8");
  338. + if (font == NULL) {
  339. + error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
  340. + goto out;
  341. + }
  342. +
  343. + if (*font == '\0') {
  344. + error("%s: invalid '%s.Font' entry in %s", Name, section, cfg_source());
  345. + goto out_free;
  346. + }
  347. +
  348. + XRES = -1;
  349. + YRES = -1;
  350. + if (sscanf(font, "%dx%d", &XRES, &YRES) != 2 ||
  351. + XRES < 1 ||
  352. + YRES < 1) {
  353. + error("%s: bad Font '%s' from %s", Name, font, cfg_source());
  354. + goto out_free;
  355. + }
  356. +
  357. + if (XRES != 6 && YRES != 8) {
  358. + error("%s: bad Font '%s' from %s (only 6x8 at the moment)",
  359. + Name, font, cfg_source());
  360. + goto out_free;
  361. + }
  362. +
  363. + error("%s: font '%s' selected", Name, font);
  364. +
  365. + ret = 0;
  366. +
  367. +out_free:
  368. + free(font);
  369. +out:
  370. + return ret;
  371. +}
  372. +
  373. +static int drv_TEW673GRU_start(const char *section)
  374. +{
  375. + int ret;
  376. +
  377. + DCOLS = TEW673GRU_NUM_COLS;
  378. + DROWS = TEW673GRU_NUM_ROWS;
  379. +
  380. + if (MODE) {
  381. + ret = drv_TEW673GRU_init_font(section);
  382. + if (ret)
  383. + goto err;
  384. +
  385. + FB_SIZE = DCOLS * TEW673GRU_BPP;
  386. + } else {
  387. + XRES = 10;
  388. + YRES = 16;
  389. + DCOLS = DCOLS / XRES;
  390. + DROWS = DROWS / YRES;
  391. +
  392. + FB_SIZE = DCOLS * DROWS;
  393. + }
  394. +
  395. + if (FB_SIZE) {
  396. + drv_TEW673GRU_FB = malloc(FB_SIZE);
  397. + if (drv_TEW673GRU_FB == NULL) {
  398. + error("%s: framebuffer could not be allocated", Name);
  399. + goto err;
  400. + }
  401. + }
  402. +
  403. + ret = drv_TEW673GRU_open(section);
  404. + if (ret < 0)
  405. + goto err_free;
  406. +
  407. + if (MODE == 0)
  408. + drv_TEW673GRU_clear_screen();
  409. +
  410. + return 0;
  411. +
  412. + err_free:
  413. + if (drv_TEW673GRU_FB)
  414. + free(drv_TEW673GRU_FB);
  415. + err:
  416. + return -1;
  417. +}
  418. +
  419. +static int drv_TEW673GRU_greet(const char *msg1, const char *msg2)
  420. +{
  421. + if (MODE)
  422. + return drv_generic_graphic_greet(msg1, msg2);
  423. +
  424. + return drv_generic_text_greet(msg1, msg2);
  425. +}
  426. +
  427. +
  428. +/****************************************/
  429. +/*** widget callbacks ***/
  430. +/****************************************/
  431. +
  432. +
  433. +/* using drv_generic_text_draw(W) */
  434. +/* using drv_generic_text_icon_draw(W) */
  435. +/* using drv_generic_text_bar_draw(W) */
  436. +/* using drv_generic_gpio_draw(W) */
  437. +
  438. +
  439. +/****************************************/
  440. +/*** exported functions ***/
  441. +/****************************************/
  442. +
  443. +int drv_TEW673GRU_list(void)
  444. +{
  445. + printf("TEW673GRU driver");
  446. + return 0;
  447. +}
  448. +
  449. +int drv_TEW673GRU_init(const char *section, const int quiet)
  450. +{
  451. + WIDGET_CLASS wc;
  452. + int ret;
  453. +
  454. + cfg_number(section, "Mode", 0, 0, 1, &MODE);
  455. +
  456. + if (MODE) {
  457. + drv_generic_graphic_real_blit = drv_TEW673GRU_blit;
  458. + drv_generic_graphic_real_clear = drv_TEW673GRU_clear;
  459. + } else {
  460. + drv_generic_text_real_write = drv_TEW673GRU_write;
  461. + }
  462. +
  463. + ret = drv_TEW673GRU_start(section);
  464. + if (ret)
  465. + return ret;
  466. +
  467. + if (MODE) {
  468. + ret = drv_generic_graphic_init(section, Name);
  469. + if (ret)
  470. + return ret;
  471. + } else {
  472. + ret = drv_generic_text_init(section, Name);
  473. + if (ret)
  474. + return ret;
  475. +
  476. + ret = drv_generic_text_icon_init();
  477. + if (ret != 0)
  478. + return ret;
  479. +
  480. + ret = drv_generic_text_bar_init(1);
  481. + if (ret != 0)
  482. + return ret;
  483. +
  484. + drv_generic_text_bar_add_segment(0, 0, 255, ' ');
  485. + drv_generic_text_bar_add_segment(255, 255, 255, '#');
  486. +
  487. + wc = Widget_Text;
  488. + wc.draw = drv_generic_text_draw;
  489. + widget_register(&wc);
  490. +
  491. + wc = Widget_Icon;
  492. + wc.draw = drv_generic_text_icon_draw;
  493. + widget_register(&wc);
  494. +
  495. + wc = Widget_Bar;
  496. + wc.draw = drv_generic_text_bar_draw;
  497. + widget_register(&wc);
  498. + }
  499. +
  500. + if (!quiet) {
  501. + char buffer[40];
  502. + qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
  503. + drv_TEW673GRU_greet(buffer, "www.openwrt.org");
  504. + sleep(3);
  505. + drv_TEW673GRU_clear_screen();
  506. + }
  507. +
  508. + return 0;
  509. +}
  510. +
  511. +int drv_TEW673GRU_quit(const int quiet)
  512. +{
  513. +
  514. + info("%s: shutting down.", Name);
  515. +
  516. + drv_TEW673GRU_clear_screen();
  517. +
  518. + if (!quiet)
  519. + drv_TEW673GRU_greet("goodbye!", NULL);
  520. +
  521. + if (MODE)
  522. + drv_generic_graphic_quit();
  523. + else
  524. + drv_generic_text_quit();
  525. +
  526. + debug("closing connection");
  527. + drv_TEW673GRU_close();
  528. +
  529. + return (0);
  530. +}
  531. +
  532. +DRIVER drv_TEW673GRU = {
  533. + .name = Name,
  534. + .list = drv_TEW673GRU_list,
  535. + .init = drv_TEW673GRU_init,
  536. + .quit = drv_TEW673GRU_quit,
  537. +};
  538. --- a/lcd4linux.conf.sample
  539. +++ b/lcd4linux.conf.sample
  540. @@ -581,6 +581,11 @@ Display FutabaVFD {
  541. }
  542. }
  543. +Display TEW673GRU {
  544. + Driver 'TEW673GRU'
  545. + Font '6x8'
  546. + Port '/dev/spidev1.0'
  547. +}
  548. #Plugin KVV {
  549. # StationID '12_701'