diff --git a/Makefile.am b/Makefile.am index 4ab4748..92acee1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -119,6 +119,7 @@ drv_T6963.c \ drv_TeakLCM.c \ drv_Trefon.c \ drv_ula200.c \ +drv_USB2VFD.c \ drv_USBHUB.c \ drv_USBLCD.c \ drv_vnc.c \ diff --git a/drivers.m4 b/drivers.m4 index c3b9d46..7c25aad 100644 --- a/drivers.m4 +++ b/drivers.m4 @@ -39,7 +39,7 @@ AC_ARG_WITH( [ Newhaven, Noritake, NULL, Pertelian, PHAnderson,] [ PICGraphic, picoLCD, picoLCDGraphic, PNG, PPM, RouterBoard,] [ Sample, SamsungSPF, serdisplib, ShuttleVFD, SimpleLCD, st2205, T6963,] - [ TeakLCM, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11], + [ TeakLCM, Trefon, ULA200, USB2VFD, USBHUB, USBLCD, VNC, WincorNixdorf, X11], drivers=$withval, drivers=all ) @@ -110,6 +110,7 @@ for driver in $drivers; do TeakLCM="yes" Trefon="yes" ULA200="yes" + USB2VFD="yes" USBHUB="yes" USBLCD="yes" VNC="yes" @@ -266,6 +267,9 @@ for driver in $drivers; do ULA200) ULA200=$val ;; + USB2VFD) + USB2VFD=$val + ;; USBHUB) USBHUB=$val ;; @@ -819,6 +823,13 @@ if test "$ULA200" = "yes"; then fi fi +if test "$USB2VFD" = "yes"; then + TEXT="yes" + SERIAL="yes" + DRIVERS="$DRIVERS drv_USB2VFD.o" + AC_DEFINE(WITH_USB2VFD,1,[USB2VFD driver]) +fi + if test "$USBHUB" = "yes"; then if test "$has_usb" = "true"; then GPIO="yes" diff --git a/drv.c b/drv.c index b1b5a17..e4c8b1b 100644 --- a/drv.c +++ b/drv.c @@ -95,6 +95,7 @@ extern DRIVER drv_T6963; extern DRIVER drv_TeakLCM; extern DRIVER drv_Trefon; extern DRIVER drv_ula200; +extern DRIVER drv_USB2VFD; extern DRIVER drv_USBHUB; extern DRIVER drv_USBLCD; extern DRIVER drv_vnc; @@ -254,6 +255,9 @@ DRIVER *Driver[] = { #ifdef WITH_ULA200 &drv_ula200, #endif +#ifdef WITH_USB2VFD + &drv_USB2VFD, +#endif #ifdef WITH_USBHUB &drv_USBHUB, #endif diff --git a/drv_USB2VFD.c b/drv_USB2VFD.c new file mode 100644 index 0000000..8c14477 --- /dev/null +++ b/drv_USB2VFD.c @@ -0,0 +1,277 @@ +/* $Id$ + * $URL$ + * + * driver for the Aliexpress AIDA64 USB2VFD displays 40x2 + * they are compatible-ish with the Matrix Orbital LK displays, + * atleast that's the AIDA64 settings you have to use + * but in reality they ignore the contrast and brightness commands + * and freeze up after any command they don't like, also no custom chars + * (it only likes go-home and go-to-position, all the rest are bad) + * it also only displays anything if the display buffer is completely filled + * special characters: | is °C, \DEL (0x7F) is a full block + * + * Copyright (C) 2025 Marceline + * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * + * exported fuctions: + * + * struct DRIVER drv_USB2VFD + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "debug.h" +#include "cfg.h" +#include "qprintf.h" +#include "udelay.h" +#include "plugin.h" +#include "widget.h" +#include "widget_text.h" +#include "widget_icon.h" +#include "widget_bar.h" +#include "drv.h" + +/* text mode display? */ +#include "drv_generic_text.h" + +/* serial port? */ +#include "drv_generic_serial.h" + +static char Name[] = "USB2VFD"; + +static char dispBuffer[2][44]; + +/****************************************/ +/*** hardware dependant functions ***/ +/****************************************/ + +static int drv_USB2VFD_open(const char *section) +{ + /* open serial port */ + /* don't mind about device, speed and stuff, this function will take care of */ + + if (drv_generic_serial_open(section, Name, 0) < 0) + return -1; + + return 0; +} + + +static int drv_USB2VFD_close(void) +{ + /* close whatever port you've opened */ + drv_generic_serial_close(); + + return 0; +} + + +/* dummy function that sends something to the display */ +static void drv_USB2VFD_send(const char *data, const unsigned int len) +{ + drv_generic_serial_write(data, len); +} + +/* text mode displays only */ +static void drv_USB2VFD_write(const int row, const int col, const char *data, int len) +{ + int i; + char home[2] = { 0xFE, 0x48 }; + char line2[4] = { 0xFE, 0x47, 0x01, 0x02 }; + + strncpy(&(dispBuffer[row][col]), data, len); + + drv_USB2VFD_send(home, 2); + drv_USB2VFD_send(dispBuffer[0], DCOLS); + drv_USB2VFD_send(line2, 4); + drv_USB2VFD_send(dispBuffer[1], DCOLS); +} + +/* text mode displays only */ +static void drv_USB2VFD_clear(void) // ~stolen~ borrowed from the MatrixOrbital Driver +{ + int i, j; + + for (i = 0; i < DROWS; i++) { + for (j = 0; j < DCOLS + 4; j++) { + dispBuffer[i][j] = ' '; + } + drv_USB2VFD_write(1, i + 1, dispBuffer[i], DCOLS); + } +} + +/* text mode displays only */ +static void drv_USB2VFD_defchar(const int ascii, const unsigned char *matrix) +{ + +} + +/* start text mode display */ +static int drv_USB2VFD_start(const char *section) +{ + DROWS = 2; + DCOLS = 40; + + /* open communication with the display */ + if (drv_USB2VFD_open(section) < 0) { + return -1; + } + + drv_USB2VFD_clear(); /* clear display */ + + return 0; +} + + +/****************************************/ +/*** plugins ***/ +/****************************************/ + +/* none */ + + +/****************************************/ +/*** widget callbacks ***/ +/****************************************/ + + +/* using drv_generic_text_draw(W) */ + + +/****************************************/ +/*** exported functions ***/ +/****************************************/ + + +/* list models */ +int drv_USB2VFD_list(void) +{ + printf("USB2VFD driver"); + return 0; +} + + +/* initialize driver & display */ +/* use this function for a text display */ +int drv_USB2VFD_init(const char *section, const int quiet) +{ + WIDGET_CLASS wc; + int ascii; + int ret; + + info("%s: %s", Name, "$Rev$"); + + /* display preferences */ + XRES = 5; /* pixel width of one char */ + YRES = 8; /* pixel height of one char */ + CHARS = 8; /* number of user-defineable characters */ + CHAR0 = 0; /* ASCII of first user-defineable char */ + GOTO_COST = 4; /* number of bytes a goto command requires */ + + /* real worker functions */ + drv_generic_text_real_write = drv_USB2VFD_write; + drv_generic_text_real_defchar = NULL; + + /* start display */ + if ((ret = drv_USB2VFD_start(section)) != 0) + return ret; + + if (!quiet) { + char buffer[40]; + qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS); + if (drv_generic_text_greet(buffer, "Marceline the Vampire Queen!")) { + sleep(3); + drv_USB2VFD_clear(); + } + } + + /* initialize generic text driver */ + if ((ret = drv_generic_text_init(section, Name)) != 0) + return ret; + + /* initialize generic bar driver */ + if ((ret = drv_generic_text_bar_init(1)) != 0) + return ret; + + cfg_number(section, "BarChar", 0x7F, 1, 255, &ascii); + + /* add fixed chars to the bar driver */ + drv_generic_text_bar_add_segment(0, 0, 255, 32); /* ASCII 32 = blank */ + drv_generic_text_bar_add_segment(255, 255, 255, ascii); + + + /* register text widget */ + wc = Widget_Text; + wc.draw = drv_generic_text_draw; + widget_register(&wc); + + /* register bar widget */ + wc = Widget_Bar; + wc.draw = drv_generic_text_bar_draw; + widget_register(&wc); + + /* register plugins */ + // AddFunction("LCD::contrast", 1, plugin_contrast); + + return 0; +} + + +/* close driver & display */ +/* use this function for a text display */ +int drv_USB2VFD_quit(const int quiet) +{ + + info("%s: shutting down.", Name); + + drv_generic_text_quit(); + + /* clear display */ + drv_USB2VFD_clear(); + + /* say goodbye... */ + if (!quiet) { + drv_generic_text_greet("goodbye!", NULL); + } + + debug("closing connection"); + drv_USB2VFD_close(); + + return (0); +} + + +/* use this one for a text display */ +DRIVER drv_USB2VFD = { + .name = Name, + .list = drv_USB2VFD_list, + .init = drv_USB2VFD_init, + .quit = drv_USB2VFD_quit, +};