From b2da58a5b01e9f9e08f8b7768ffc2a9d2c1f53f8 Mon Sep 17 00:00:00 2001 From: marschap Date: Sun, 23 Nov 2008 13:09:11 +0000 Subject: [PATCH] isupport Siemens/Wincor Nixdorf BA63/66 in the serialVFD driver (Stefan Herdler) --- ChangeLog | 1 + LCDd.conf | 1 + docs/lcdproc-user/drivers/serialVFD.docbook | 29 +++- server/drivers/serialVFD.c | 138 ++++++++++++-------- server/drivers/serialVFD.h | 2 +- server/drivers/serialVFD_displays.c | 100 +++++++++++++- server/drivers/serialVFD_io.c | 6 + 7 files changed, 219 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index a945ee4..a530169 100644 --- a/ChangeLog +++ b/ChangeLog @@ -60,6 +60,7 @@ v.0.5dev (ongoing development) * new make targets to compile & install server & clients separately * autoconf fixes: check for pkg-config macros + new driver irtrans (Phant0m / Aron Parsons) + + serialVFD driver: support Siemens/Wincor Nixdorf BA63/66 (Stefan Herdler) v.0.5.2 * fix switching on/off the Load screen in lcdproc client using the menu diff --git a/LCDd.conf b/LCDd.conf index 660123a..ea2f94f 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -887,6 +887,7 @@ Speed=9600 # 5 IEE S03601-96-080 (*) # 6 Futaba NA202SD08FA (allmost IEE compatible) # 7 Samsung 20S207DA4 and 20S207DA6 +# 8 Nixdorf BA6x / VT100 # (* most should work, not testet yet.) Type=0 diff --git a/docs/lcdproc-user/drivers/serialVFD.docbook b/docs/lcdproc-user/drivers/serialVFD.docbook index 25a131d..ad46cf0 100644 --- a/docs/lcdproc-user/drivers/serialVFD.docbook +++ b/docs/lcdproc-user/drivers/serialVFD.docbook @@ -64,7 +64,7 @@ Feedback is welcome. KD Rev 2.1 AT90S.... microcontroller Ok - Ok + - Yes 1, 0 @@ -166,6 +166,16 @@ Feedback is welcome. 5 + + Siemens/Wincor Nixdorf BA63/66 + ? + Ok + - + Yes + 8 + Display needs different connection, see below! + no Custom-Characters, no brightness-control + @@ -319,6 +329,19 @@ Pin 19 ------ RxD ]]> + +Siemens/Wincor Nixdorf BA63/66: +This display doesn't need the inverter! +It must be connected directly with the serial port. + +Check the serial port setup of the display, it has to be "9600 8N1". In most cases JP3 needs to be modified (closed) by the user! + + + +More detailed information can be found in the users manual of +the display. + @@ -530,6 +553,10 @@ Number of Custom-Characters [default: Display-Type dependent] 7 Samsung 20S207DA? + + 8 + Siemens/Wincor Nixdorf BA63/66 + diff --git a/server/drivers/serialVFD.c b/server/drivers/serialVFD.c index 6c08bb8..4db881f 100644 --- a/server/drivers/serialVFD.c +++ b/server/drivers/serialVFD.c @@ -91,6 +91,7 @@ get_info Implemented. #define init_cmds 7 //commands needed to initialize the display. #define set_user_char 8 //set user character. #define hor_tab 9 //moves cursor 1 chr right +#define next_line 10 //moves cursor to the first character of the next line (= LF + CR) #define LPTPORT 0x378 /* Vars for the server core */ @@ -103,6 +104,7 @@ MODULE_EXPORT char *symbol_prefix = "serialVFD_"; static void serialVFD_init_vbar (Driver *drvthis); static void serialVFD_init_hbar (Driver *drvthis); static void serialVFD_put_char (Driver *drvthis, int n); +static void serialVFD_hw_write (Driver *drvthis, int i); // Opens com port and sets baud correctly... // @@ -129,6 +131,7 @@ serialVFD_init (Driver *drvthis) p->refresh_timer = 480; p->hw_brightness = 0; p->para_wait = DEFAULT_PARA_WAIT; + p->hw_cmd[next_line][0] = 0; debug(RPT_INFO, "%s(%p)", __FUNCTION__, drvthis); @@ -403,7 +406,7 @@ serialVFD_set_char (Driver *drvthis, int n, unsigned char *dat) static void serialVFD_put_char (Driver *drvthis, int n) -{ // put char in display +{ // put userchar in display PrivateData *p = drvthis->private_data; Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[set_user_char][1],\ @@ -413,7 +416,6 @@ serialVFD_put_char (Driver *drvthis, int n) } - ///////////////////////////////////////////////////////////// // Blasts a single frame onscreen, to the lcd... // @@ -438,7 +440,7 @@ serialVFD_flush (Driver *drvthis) } if (p->refresh_timer > 500) { // Do a full refresh every 500 refreshs. - // With this it is possible to switch display on and off while lcdproc is running + // With this it is possible to switch the display on and off while LCDd is running Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[p->hw_brightness][1],\ @@ -453,73 +455,107 @@ serialVFD_flush (Driver *drvthis) p->refresh_timer++; - if (p->display_type != 1) { //not KD Rev 2.1 + if (p->display_type == 1) { // KD Rev 2.1 only + if (custom_char_changed[p->last_custom]) + p->last_custom = -10; + } + else { // other Displays for (i = 0; i < p->customchars; i++) // set customcharacters if (custom_char_changed[i]) serialVFD_put_char(drvthis, i); - } - - if (custom_char_changed[p->last_custom]) - p->last_custom = -10; - - if (p->hw_cmd[mv_cursor][0] == 0) { // Workaround for Displays that doesn't support mv_cursor command - Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[pos1_cursor][1], p->hw_cmd[pos1_cursor][0]); - last_chr = -1; } - for (i = 0; i < (p->height * p->width); i++) { - /* Backing-store implementation. If it's already - * on the screen, don't put it there again - */ - - if ((p->framebuf[i] != p->backingstore[i]) || - ((p->framebuf[i] <= 30) && (custom_char_changed[(int)p->framebuf[i]] != 0))) { - if (last_chr < i-1) { // if not last char written cursor has to be moved. - if (((p->hw_cmd[hor_tab][0] * (i-1-last_chr)) > (p->hw_cmd[mv_cursor][0]+1)) && (p->hw_cmd[mv_cursor][0] != 0)) { - Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[mv_cursor][1], - p->hw_cmd[mv_cursor][0]); - Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *) &i, 1); -//report(RPT_WARNING, "%s: move %d", drvthis->name, i); - } - else { - for (j = last_chr; j < (i-1); j++) - Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]); -//report(RPT_WARNING, "%s: TAB %d", drvthis->name, j-last_chr); - } - } - - if (p->framebuf[i] <= 30) { // custom character - if (p->display_type == 1) { // KD Rev 2.1 only - if (p->last_custom != p->framebuf[i]) { - // substitute and select character to overwrite (237) - Port_Function[p->use_parallel].write_fkt(drvthis, "\x1A\xDB", 2); - // overwrite selected character - Port_Function[p->use_parallel].write_fkt(drvthis, &p->custom_char[(int)p->framebuf[i]][0], 7); + if (p->hw_cmd[next_line][0] == 0) { // normal mode Display + if (p->hw_cmd[mv_cursor][0] == 0) { // Workaround for Displays that doesn't support mv_cursor command + Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[pos1_cursor][1], p->hw_cmd[pos1_cursor][0]); + last_chr = -1; + } + + for (i = 0; i < (p->height * p->width); i++) { + + /* Backing-store implementation. If it's already + * on the screen, don't put it there again + */ + + if ((p->framebuf[i] != p->backingstore[i]) || (p->hw_cmd[hor_tab][0] == 0) || + ((p->framebuf[i] <= 30) && (custom_char_changed[(int)p->framebuf[i]] != 0))) { + if (last_chr < i-1) { // if not last char written cursor has to be moved. + if (((p->hw_cmd[hor_tab][0] * (i-1-last_chr)) > (p->hw_cmd[mv_cursor][0]+1)) && (p->hw_cmd[mv_cursor][0] != 0)) { + Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[mv_cursor][1], + p->hw_cmd[mv_cursor][0]); + Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *) &i, 1); + //report(RPT_WARNING, "%s: move %d", drvthis->name, i); + } + else { + for (j = last_chr; j < (i-1); j++) + Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]); + //report(RPT_WARNING, "%s: TAB %d", drvthis->name, j-last_chr); } - Port_Function[p->use_parallel].write_fkt(drvthis, "\xDB", 1); // write character - p->last_custom = p->framebuf[i]; - } - else { // all other displays - Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *) &p->usr_chr_mapping[(int)p->framebuf[i]], 1); } + serialVFD_hw_write(drvthis, i); + last_chr = i; } - else if ((p->framebuf[i] == 127) || ((p->framebuf[i] > 127) && (p->ISO_8859_1 != 0))) { // ISO_8859_1 translation for 129 ... 255 - Port_Function[p->use_parallel].write_fkt(drvthis, &p->charmap[p->framebuf[i] - 127], 1); + } + } + + else { // line mode Display (partitially borrowed from serialPOS.c) + for (j = 0; j < p->height; j++) { + // set pointers to start of the line in frame buffer & backing store + unsigned char *sp = p->framebuf + (j * p->width); + unsigned char *sq = p->backingstore + (j * p->width); + if (j == 0) { + Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[pos1_cursor][1], p->hw_cmd[pos1_cursor][0]); } else { - Port_Function[p->use_parallel].write_fkt(drvthis, &p->framebuf[i], 1); + Port_Function[p->use_parallel].write_fkt(drvthis, &p->hw_cmd[next_line][1], p->hw_cmd[next_line][0]); } - - last_chr = i; + // skip over identical lines + if ( memcmp(sp, sq, p->width) == 0) { + /* The lines are the same. */ + continue; + } + for (i = 0; i < p->width; i++) { + serialVFD_hw_write(drvthis, (i + (j * p->width))); + } + last_chr = 10; } } if (last_chr >= 0) { // update backingstore if something changed memcpy(p->backingstore, p->framebuf, p->height * p->width); -//report(RPT_WARNING, "%s: memcpy", drvthis->name); + //report(RPT_WARNING, "%s: memcpy", drvthis->name); } + +} + +static void +serialVFD_hw_write (Driver *drvthis, int i) +{ // finally write character/usercharacter on the display + PrivateData *p = drvthis->private_data; + + if (p->framebuf[i] <= 30) { // custom character + if (p->display_type == 1) { // KD Rev 2.1 only + if (p->last_custom != p->framebuf[i]) { + // substitute and select character to overwrite (237) + Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *)"\x1A\xDB", 2); + // overwrite selected character + Port_Function[p->use_parallel].write_fkt(drvthis, &p->custom_char[(int)p->framebuf[i]][0], 7); + } + Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *)"\xDB", 1); // write character + p->last_custom = p->framebuf[i]; + } + else { // all other displays + Port_Function[p->use_parallel].write_fkt(drvthis, (unsigned char *) &p->usr_chr_mapping[(int)p->framebuf[i]], 1); + } + } + else if ((p->framebuf[i] == 127) || ((p->framebuf[i] > 127) && (p->ISO_8859_1 != 0))) { // ISO_8859_1 translation for 129 ... 255 + Port_Function[p->use_parallel].write_fkt(drvthis, &p->charmap[p->framebuf[i] - 127], 1); + } + else { + Port_Function[p->use_parallel].write_fkt(drvthis, &p->framebuf[i], 1); + } } diff --git a/server/drivers/serialVFD.h b/server/drivers/serialVFD.h index 57b6821..e02238c 100644 --- a/server/drivers/serialVFD.h +++ b/server/drivers/serialVFD.h @@ -100,7 +100,7 @@ typedef struct driver_private_data { int last_custom; // last custom character written unsigned char custom_char[31][7]; // stored custom characters unsigned char custom_char_store[31][7]; // custom characters backingstore - unsigned char hw_cmd[10][4]; // hardwarespecific commands + unsigned char hw_cmd[11][10]; // hardwarespecific commands int usr_chr_dot_assignment[57]; // how to setup usercharacters unsigned int usr_chr_mapping[31];// where to place the usercharacters (0..30) in the asciicode unsigned int usr_chr_load_mapping[31];// needed for displays with different read and write mapping diff --git a/server/drivers/serialVFD_displays.c b/server/drivers/serialVFD_displays.c index cb55369..8633a5f 100644 --- a/server/drivers/serialVFD_displays.c +++ b/server/drivers/serialVFD_displays.c @@ -40,7 +40,7 @@ void serialVFD_load_IEE_95B (Driver *drvthis); void serialVFD_load_IEE_96 (Driver *drvthis); void serialVFD_load_Futaba_NA202SD08FA(Driver *drvthis); void serialVFD_load_Samsung (Driver *drvthis); - +void serialVFD_load_Nixdorf_BA6x (Driver *drvthis); int serialVFD_load_display_data(Driver *drvthis) { @@ -70,6 +70,9 @@ int serialVFD_load_display_data(Driver *drvthis) case 7: serialVFD_load_Samsung(drvthis); break; + case 8: + serialVFD_load_Nixdorf_BA6x(drvthis); + break; default: return -1; break; @@ -95,17 +98,22 @@ serialVFD_load_NEC_FIPC (Driver *drvthis) // hw_cmd[Command][data] = {{commandlength , command 1}, // ..... // {commandlength , command N}} - const char hw_cmd[10][4] = {{1 ,0x04}, // dark + const char hw_cmd[11][4] = {{1 ,0x04}, // dark {1 ,0x03}, {1 ,0x02}, {1 ,0x01}, // bright - {1 ,0x0D}, // pos1 + {1 ,0x0D}, // pos1 + // pos1 command is only used (and needed), when mv_cursor command is not supported {1 ,0x1B}, // move cursor (set to 0 if not supported) {1 ,0x0C}, // reset {2 ,0x14, 0x11}, // init {1 ,0x1A}, // set user char - {1 ,0x09}}; // tab - for (tmp = 0; tmp < 10; tmp++) + {1 ,0x09}, // tab + {0 }}; // next_line (only used in line mode) + // Line mode will be used if Next_line command is set!!! + // Do not set if the display supports normal mode (most displays should do this). + + for (tmp = 0; tmp < 11; tmp++) for (w = 0; w < 4; w++) p->hw_cmd[tmp][w] = hw_cmd[tmp][w]; @@ -154,6 +162,15 @@ serialVFD_load_NEC_FIPC (Driver *drvthis) {0xAF,0,0,0,0,0, 0x5F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0, 0x5F, 0xE1, 0xE3, 0xE4}; for (tmp = 0; tmp < 31; tmp++) p->usr_chr_mapping[tmp] = usr_chr_mapping[tmp]; + + // The following is only needet to set if the display needs a different setting + // for loading the usercharacters. + // Example: The character loaded to 0x00 will be shown at 0xFD. + // usr_chr_load_mapping[0] or usr_chr_load_mapping[1] has to be != 0 + //const unsigned int usr_chr_load_mapping[31]= + //{ 0x02, 0x01, 0x00}; + //for (tmp = 0; tmp < 31; tmp++) + // p->usr_chr_load_mapping[tmp] = usr_chr_load_mapping[tmp]; } @@ -697,3 +714,76 @@ serialVFD_load_Samsung (Driver *drvthis) for (tmp = 0; tmp < 31; tmp++) p->usr_chr_mapping[tmp] = usr_chr_mapping[tmp]; } + +void +serialVFD_load_Nixdorf_BA6x (Driver *drvthis) +{ // Nixdorf BA63 & BA66 + PrivateData *p = (PrivateData*) drvthis->private_data; + int tmp, w; + + //if (p->customchars == -83) // display doesn't support custom characters + p->customchars = 0; // number of custom characters the display provides + p->vbar_cc_offset = 5; // character offset of the bars + p->hbar_cc_offset = 12; // character offset of the bars + p->predefined_hbar = 1; // the display has predefined hbar-characters + p->predefined_vbar = 1; // the display has predefined vbar-characters + + // hardwarespecific commands: + // hw_cmd[Command][data] = {{commandlength , command 1}, + // ..... + // {commandlength , command N}} + const char hw_cmd[11][10] = {{0 }, // dark + {0 }, + {0 }, + {0 }, // bright + {6 ,0x1B, 0x5B, '1', 0x3B, '1', 0x48}, // pos1 + // pos1 command is only used (and needed), when mv_cursor command is not supported + {0 }, // move cursor + {4 ,0x1B, 0x5B, 0x32, 0x4A}, // reset + {3 ,0x1B, 0x52, 0x00}, // init + {0 }, // set user char + {0 }, // tab + {2 ,0x0D, 0x0A} // next_line + // Next_line command is only used in line mode. + // Line mode will be used if Next_line command is set!!! + // Set to "0" if display supports normal_mode! + }; + for (tmp = 0; tmp < 11; tmp++) + for (w = 0; w < 10; w++) + p->hw_cmd[tmp][w] = hw_cmd[tmp][w]; + + // Translates ISO 8859-1 to display charset. + const unsigned char charmap[] = { + 0xDB, // the "filled-block"-character usually 127 + /* #128 = 0x80 */ + 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + /* #160 = 0xA0 */ + 160, 0xAD, 0x9B, 0x9C, 0xC8, 0x9D, 0x7C, 0xC0, + '"', '?', 0xA6, 0xAE, 0xAA, '-', '?', '?', + 0xEF, 0xCA, 0xC6, 0xC7, 0x27, 0xB8, '?', '.', + ',', '?', 0xA7, 0xAF, 0xAC, 0xAB, '?', 0xA8, + /* #192 = 0xC0 */ + 0xD0, 'A', 0xD5, 'A', 0x8E, 0x8F, 0x92, 0x80, + 0xD1, 0x90, 0xD6, 0xD3, 'I', 'I', 0xD7, 0xD4, + 'D', 0xA5, 'O', 'O', 0xD8, 'O', 0x99, 'x', + '0', 0xD2, 'U', 0xD9, 0x9A, 'Y', 'p', 0xB1, + /* #224 = 0xE0 */ + 0x85, 0xA0, 0x83, 'a', 0x84, 0x86, 0x91, 0x87, + 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, + 'o', 0xA4, 0x95, 0xA9, 0x93, 'o', 0x94, '/', + '0', 0x97, 0xA3, 0x96, 0x81, 'y', 'p', 0x89 }; + for (tmp = 0; tmp < 129; tmp++) + p->charmap[tmp] = charmap[tmp]; + + + // Where to place the usercharacters (0..30) in the asciicode. + // Also used to map standardcharacters in the usercharacterspace(0..30) + // (useful for displays with less then 30 usercharacters and predefined bars) + const unsigned int usr_chr_mapping[31]= + {0,0,0,0,0,0, ' ', ' ', 0xDC, 0xDC, 0xDC, 0xDB, 0, ' ', 0xDD, 0xDD, 0xDB}; + for (tmp = 0; tmp < 31; tmp++) + p->usr_chr_mapping[tmp] = usr_chr_mapping[tmp]; +} diff --git a/server/drivers/serialVFD_io.c b/server/drivers/serialVFD_io.c index 0ef57e9..28e6a89 100644 --- a/server/drivers/serialVFD_io.c +++ b/server/drivers/serialVFD_io.c @@ -44,6 +44,9 @@ void serialVFD_write_serial (Driver *drvthis, unsigned char *dat, size_t length) { + if (length <= 0) + return; + PrivateData *p = drvthis->private_data; write(p->fd,dat,length); } @@ -51,6 +54,9 @@ serialVFD_write_serial (Driver *drvthis, unsigned char *dat, size_t length) void serialVFD_write_parallel (Driver *drvthis, unsigned char *dat, size_t length) { + if (length <= 0) + return; + #ifdef HAVE_PCSTYLE_LPT_CONTROL PrivateData *p = drvthis->private_data; int i_para, j_para;