From c9623a72daed2eda2e726be0cd45c5778b4be843 Mon Sep 17 00:00:00 2001 From: mmdolze Date: Sat, 23 Jan 2010 17:48:00 +0000 Subject: [PATCH] Add a flush method to the hardware depended functions. It is called whenever a sequence of characters or commands have to be terminated (common_init, position, flush). Modify the lcd2usb subdriver to implement a small command buffer and implement flush(). --- ChangeLog | 1 + server/drivers/hd44780-lcd2usb.c | 70 +++++++++++++++++++------------- server/drivers/hd44780-lcd2usb.h | 3 ++ server/drivers/hd44780-low.h | 5 +++ server/drivers/hd44780.c | 7 ++++ 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1bdb92..6c25001 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ v.0.5dev (ongoing development) * hd44780: Change mapping for spanish 'n with tilde' characters * hd44780: Exclude pin for switchable backlight from keypad scanning * server core: New network input buffering + * hd44780: Extended subdriver API and performance improvement for lcd2usb v0.5.3 + lcdexec: notification when called program finishes diff --git a/server/drivers/hd44780-lcd2usb.c b/server/drivers/hd44780-lcd2usb.c index daff0e0..81fb776 100644 --- a/server/drivers/hd44780-lcd2usb.c +++ b/server/drivers/hd44780-lcd2usb.c @@ -31,6 +31,12 @@ void lcd2usb_HD44780_backlight(PrivateData *p, unsigned char state); unsigned char lcd2usb_HD44780_scankeypad(PrivateData *p); void lcd2usb_HD44780_close(PrivateData *p); void lcd2usb_HD44780_set_contrast(PrivateData *p, unsigned char value); +void lcd2usb_HD44780_flush(PrivateData *p); + +/* small data buffer */ +unsigned char buffer[LCD2USB_MAX_CMD]; +int buffer_current_type_id = -1; +int buffer_current_use = 0; /** @@ -63,6 +69,7 @@ hd_init_lcd2usb(Driver *drvthis) p->hd44780_functions->scankeypad = lcd2usb_HD44780_scankeypad; p->hd44780_functions->close = lcd2usb_HD44780_close; p->hd44780_functions->set_contrast = lcd2usb_HD44780_set_contrast; + p->hd44780_functions->flush = lcd2usb_HD44780_flush; /* try to find USB device */ #if 0 @@ -116,9 +123,9 @@ hd_init_lcd2usb(Driver *drvthis) return 0; } - /** - * Send data or commands to the display. + * Send data or command to the display. The data/command is internally + * queued. * \param p Pointer to driver's private data structure. * \param displayID ID of the display (or 0 for all) to send data to. * \param flags Defines whether to end a command or data. @@ -131,9 +138,41 @@ lcd2usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char int id = (displayID == 0) ? LCD2USB_CTRL_BOTH : ((displayID == 1) ? LCD2USB_CTRL_0 : LCD2USB_CTRL_1); - usb_control_msg(p->usbHandle, USB_TYPE_VENDOR, (type | id), ch, 0, NULL, 0, 1000); + /* flush current buffer if target or command type are different */ + if ((buffer_current_type_id >= 0) && (buffer_current_type_id != (type | id))) + lcd2usb_HD44780_flush(p); + + /* add new item to buffer */ + buffer_current_type_id = (type | id); + buffer[buffer_current_use++] = ch; + + /* flush buffer if it's full */ + if (buffer_current_use == LCD2USB_MAX_CMD) + lcd2usb_HD44780_flush(p); } +/** + * Actually send data or command to the display. + * \param p Pointer to driver's private data structure. + */ +void +lcd2usb_HD44780_flush(PrivateData *p) +{ + /* only if some data available */ + if (buffer_current_use == 0) + return; + + /* construct and send message */ + usb_control_msg(p->usbHandle, USB_TYPE_VENDOR, + buffer_current_type_id | (buffer_current_use - 1), + buffer[0] | (buffer[1] << 8), + buffer[2] | (buffer[3] << 8), + NULL, 0, 1000); + + /* buffer is now free again. Not necessary to clear what's in it. */ + buffer_current_type_id = -1; + buffer_current_use = 0; +} /** * Turn display backlight on or off. @@ -171,31 +210,6 @@ lcd2usb_HD44780_set_contrast(PrivateData *p, unsigned char value) } -/** - * Set on/off brightness. - * The value is not actually transmitted to the display. lcd2usb_hd44780_backlight - * has to be called to do this. - * \param drvthis Pointer to driver structure. - * \param state Brightness state (on/off) for which we want to store the value. - * \param promille New brightness in promille. - */ -void -lcd2usb_set_brightness(Driver *drvthis, int state, int promille) -{ - PrivateData *p = drvthis->private_data; - - /* check if value within range */ - if (promille < 0 || promille > 1000) - return; - - /* store the software value */ - if (state == BACKLIGHT_ON) - p->brightness = promille; - else - p->offbrightness = promille; -} - - /** * Read keypress. * \param p Pointer to driver's private data structure. diff --git a/server/drivers/hd44780-lcd2usb.h b/server/drivers/hd44780-lcd2usb.h index 3e4548e..0444473 100644 --- a/server/drivers/hd44780-lcd2usb.h +++ b/server/drivers/hd44780-lcd2usb.h @@ -8,6 +8,9 @@ #define LCD2USB_VENDORID 0x0403 #define LCD2USB_PRODUCTID 0xc630 +/* current protocol supports up to 4 bytes */ +#define LCD2USB_MAX_CMD 4 + /* target is a bit map for CMD/DATA */ #define LCD2USB_CTRL_0 (1<<3) #define LCD2USB_CTRL_1 (1<<4) diff --git a/server/drivers/hd44780-low.h b/server/drivers/hd44780-low.h index b649a2e..dfaa95a 100644 --- a/server/drivers/hd44780-low.h +++ b/server/drivers/hd44780-low.h @@ -216,6 +216,10 @@ typedef struct hwDependentFns { // ch - character to display or instruction value void (*senddata)(PrivateData *p, unsigned char dispID, unsigned char flags, unsigned char ch); + // Flush data to the display. To be used by subdrivers that + // queue from senddata internally. + void (*flush)(PrivateData *p); + // Switch the backlight on or off // state - to be or not to be on void (*backlight)(PrivateData *p, unsigned char state); @@ -242,6 +246,7 @@ typedef struct hwDependentFns { // Close the interface on shutdown void (*close)(PrivateData *p); + } HD44780_functions; /* for want of a better name :-) */ diff --git a/server/drivers/hd44780.c b/server/drivers/hd44780.c index 778e6b0..368ef16 100644 --- a/server/drivers/hd44780.c +++ b/server/drivers/hd44780.c @@ -387,6 +387,7 @@ HD44780_init(Driver *drvthis) p->hd44780_functions->scankeypad = NULL; p->hd44780_functions->output = NULL; p->hd44780_functions->close = NULL; + p->hd44780_functions->flush = NULL; // Do local (=connection type specific) display init if (init_fn(drvthis) != 0) @@ -499,6 +500,8 @@ common_init(PrivateData *p, unsigned char if_bit) p->hd44780_functions->uPause(p, 40); p->hd44780_functions->senddata(p, 0, RS_INSTR, HOMECURSOR); p->hd44780_functions->uPause(p, 1600); + if (p->hd44780_functions->flush != NULL) + p->hd44780_functions->flush(p); } @@ -627,6 +630,8 @@ HD44780_position(Driver *drvthis, int x, int y) } p->hd44780_functions->senddata(p, dispID, RS_INSTR, POSITION | DDaddr); p->hd44780_functions->uPause(p, 40); // Minimum exec time for all commands + if (p->hd44780_functions->flush != NULL) + p->hd44780_functions->flush(p); } @@ -703,6 +708,8 @@ HD44780_flush(Driver *drvthis) count++; } } + if (p->hd44780_functions->flush != NULL) + p->hd44780_functions->flush(p); debug(RPT_DEBUG, "%s: flushed %d custom chars", drvthis->name, count); }