scrolling
This commit is contained in:
parent
f1fa53fab5
commit
20d44982da
1
TODO
1
TODO
@ -1,6 +1,5 @@
|
||||
- dynamic pages
|
||||
- refresh of dynamic pages (clock, loadavg)
|
||||
- scrolling
|
||||
|
||||
- disk utilization (MB/GB)
|
||||
- mntpoints given in config
|
||||
|
163
lcd.c
163
lcd.c
@ -13,6 +13,7 @@
|
||||
#include "logging.h"
|
||||
|
||||
#define _LCD_DEBUG 1
|
||||
#define _LCD_FAKE 1
|
||||
|
||||
#define LCD_RESET_TIMEOUT_US 250000 /* 250ms */
|
||||
#define LCD_RESET_RETRY_TIMEOUT 10 /* 10s */
|
||||
@ -41,14 +42,17 @@ struct lcddev {
|
||||
int fd;
|
||||
struct termios oldtio;
|
||||
|
||||
int backlight_time;
|
||||
enum lcdstate state;
|
||||
|
||||
int (*button_cb)(struct lcddev *dev, int button, void *privdata);
|
||||
void *privdata;
|
||||
int backlight_state;
|
||||
|
||||
int (*event_callback)(struct lcddev *dev, int event, void *privdata);
|
||||
void *event_privdata;
|
||||
|
||||
const char *line_data[2];
|
||||
int scrollpos;
|
||||
int line_length[2];
|
||||
int scroll_speed;
|
||||
int scroll_pos;
|
||||
|
||||
struct event_fd *read_event;
|
||||
struct event_timeout *reset_timeout;
|
||||
@ -92,9 +96,22 @@ static int lcd_open(struct lcddev *dev, const char *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (_LCD_DEBUG > 1)
|
||||
static void lcd_dump(const char *prefix, int len, int size, const char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "%s:[%d/%d]: ", prefix, len, size);
|
||||
for (i = 0; i < len; i++)
|
||||
fprintf(stderr, "0x%X ", (unsigned char)buf[i]);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lcd_read(struct lcddev *dev, const char *buf, int len)
|
||||
{
|
||||
int retval = 0, i, cnt = 0;
|
||||
int retval = 0, cnt = 0;
|
||||
while (cnt < len) {
|
||||
retval = read(dev->fd, (char *)buf + cnt, len - cnt);
|
||||
if (retval <= 0)
|
||||
@ -102,37 +119,27 @@ static int lcd_read(struct lcddev *dev, const char *buf, int len)
|
||||
|
||||
cnt += retval;
|
||||
}
|
||||
#if _LCD_DEBUG
|
||||
fprintf(stderr, "lcd_read[%d/%d]: ", cnt, len);
|
||||
for (i = 0; i < cnt; i++)
|
||||
fprintf(stderr, "0x%X ", (unsigned char)buf[i]);
|
||||
fprintf(stderr, "\n");
|
||||
#if (_LCD_DEBUG > 1)
|
||||
lcd_dump("lcd_read", cnt, len, buf);
|
||||
#endif
|
||||
return (cnt != 0) ? cnt : retval;
|
||||
}
|
||||
|
||||
static int lcd_write(struct lcddev *dev, char *buf, int len)
|
||||
{
|
||||
int retval, i;
|
||||
int retval = write(dev->fd, buf, len);
|
||||
|
||||
retval = write(dev->fd, buf, len);
|
||||
#if _LCD_DEBUG
|
||||
fprintf(stderr, "lcd_write[%d/%d]: ", retval, len);
|
||||
for (i = 0; i < retval; i++)
|
||||
fprintf(stderr, "0x%X ", (unsigned char)buf[i]);
|
||||
|
||||
if (len == 20) {
|
||||
fprintf(stderr, "'%-16s'", buf + 4);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
#if (_LCD_DEBUG > 1)
|
||||
lcd_dump("lcd_write", retval, len, buf);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if (_LCD_FAKE == 0)
|
||||
static int lcd_reset_retry_timeout_cb(void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
dev->reset_timeout = NULL;
|
||||
|
||||
lcd_reset(dev);
|
||||
return -1; /* singleshot */
|
||||
@ -150,16 +157,30 @@ static int lcd_reset_timeout_cb(void *privdata)
|
||||
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
#endif
|
||||
|
||||
void lcd_reset(struct lcddev *dev)
|
||||
{
|
||||
#if (_LCD_DEBUG > 0)
|
||||
fprintf(stderr, "lcd_reset()\n");
|
||||
#endif
|
||||
|
||||
char cmd[] = A125_CMD_RESET;
|
||||
lcd_write(dev, cmd, sizeof(cmd));
|
||||
|
||||
dev->backlight_state = -1;
|
||||
|
||||
#if (_LCD_FAKE == 0)
|
||||
dev->state = LCD_STATE_INITIALIZING;
|
||||
|
||||
struct timeval tv = { .tv_usec = LCD_RESET_TIMEOUT_US };
|
||||
dev->reset_timeout = event_add_timeout(&tv, lcd_reset_timeout_cb, dev);
|
||||
#else
|
||||
dev->state = LCD_STATE_READY;
|
||||
|
||||
/* trigger application to set data */
|
||||
dev->event_callback(dev, LCD_EVENT_INIT, dev->event_privdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int lcd_backlight(struct lcddev *dev, int mode)
|
||||
@ -167,9 +188,17 @@ static int lcd_backlight(struct lcddev *dev, int mode)
|
||||
if (dev->state != LCD_STATE_READY)
|
||||
return -1;
|
||||
|
||||
#if (_LCD_DEBUG > 0)
|
||||
fprintf(stderr, "lcd_backlight(%d)\n", mode);
|
||||
#endif
|
||||
|
||||
if (dev->backlight_state != mode) {
|
||||
char cmd[] = A125_CMD_BACKLIGHT;
|
||||
cmd[2] = (mode) ? 0x01 : 0x00;
|
||||
lcd_write(dev, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
dev->backlight_state = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -179,6 +208,7 @@ static int lcd_backlight_timeout_cb(void *privdata)
|
||||
dev->backlight_timeout = NULL;
|
||||
|
||||
lcd_backlight(dev, 0);
|
||||
dev->event_callback(dev, LCD_EVENT_BACKLIGHT, dev->event_privdata);
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
|
||||
@ -189,10 +219,12 @@ int lcd_trigger_backlight(struct lcddev *dev, int timeout)
|
||||
dev->backlight_timeout = NULL;
|
||||
}
|
||||
|
||||
int retval = lcd_backlight(dev, 1);
|
||||
int retval = lcd_backlight(dev, (timeout == 0) ? 0 : 1);
|
||||
|
||||
if (timeout != -1) {
|
||||
struct timeval tv = { .tv_sec = timeout };
|
||||
dev->backlight_timeout = event_add_timeout(&tv, lcd_backlight_timeout_cb, dev);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -205,7 +237,6 @@ static int lcd_read_cb(int fd, void *privdata)
|
||||
int size = (dev->state != LCD_STATE_INITIALIZING) ? sizeof(buf) : 2;
|
||||
int len = lcd_read(dev, buf, size);
|
||||
|
||||
int retval = 0;
|
||||
if (dev->state == LCD_STATE_INITIALIZING) {
|
||||
char expect[] = A125_EVENT_ACTINFO;
|
||||
|
||||
@ -219,7 +250,7 @@ static int lcd_read_cb(int fd, void *privdata)
|
||||
dev->state = LCD_STATE_READY;
|
||||
|
||||
/* trigger application to set data */
|
||||
retval = dev->button_cb(dev, LCD_BUTTON0, dev->privdata);
|
||||
dev->event_callback(dev, LCD_EVENT_INIT, dev->event_privdata);
|
||||
}
|
||||
|
||||
} else if (dev->state == LCD_STATE_READY) {
|
||||
@ -230,57 +261,95 @@ static int lcd_read_cb(int fd, void *privdata)
|
||||
return 0;
|
||||
|
||||
if (memcmp(buf, expect1, sizeof(buf)) == 0) {
|
||||
retval = dev->button_cb(dev, LCD_BUTTON1, dev->privdata);
|
||||
dev->event_callback(dev, LCD_EVENT_BUTTON1, dev->event_privdata);
|
||||
|
||||
} else if (memcmp(buf, expect2, sizeof(buf)) == 0) {
|
||||
retval = dev->button_cb(dev, LCD_BUTTON2, dev->privdata);
|
||||
dev->event_callback(dev, LCD_EVENT_BUTTON2, dev->event_privdata);
|
||||
}
|
||||
}
|
||||
|
||||
if (retval)
|
||||
lcd_trigger_backlight(dev, dev->backlight_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_setline(struct lcddev *dev, int line, const char *buf)
|
||||
static int lcd_setline(struct lcddev *dev, int line, int len, const char *buf)
|
||||
{
|
||||
if (dev->state != LCD_STATE_READY)
|
||||
return -1;
|
||||
|
||||
char cmd[20] = A125_CMD_SETLINE;
|
||||
char cmd[20 +1] = A125_CMD_SETLINE;
|
||||
cmd[2] = line;
|
||||
|
||||
memset(cmd +4, ' ', 16);
|
||||
int len = strlen(buf);
|
||||
memcpy(cmd +4, buf, (len > 16) ? 16 : len);
|
||||
cmd[20] = '\0';
|
||||
|
||||
lcd_write(dev, cmd, sizeof(cmd));
|
||||
#if (_LCD_DEBUG > 0)
|
||||
fprintf(stderr, "lcd_setline(%d, '%-16s')\n", line, cmd +4);
|
||||
#endif
|
||||
|
||||
lcd_write(dev, cmd, 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_scroll_timeout_cb(void *privdata)
|
||||
{
|
||||
// TODO: scrolling
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
int i, reset_pos = 0;
|
||||
|
||||
return 0; /* periodic */
|
||||
for (i = 0; i < 2; i++) {
|
||||
int line_pos = dev->scroll_pos;
|
||||
if (line_pos < 0)
|
||||
line_pos = 0;
|
||||
|
||||
/* mark line as complete if one space is visible after message */
|
||||
if ((dev->line_length[i] - line_pos) <= 15) {
|
||||
reset_pos++;
|
||||
}
|
||||
|
||||
/* do not scroll further if message is not visible */
|
||||
if ((dev->line_length[i] - line_pos) < 0) {
|
||||
line_pos = dev->line_length[i];
|
||||
}
|
||||
|
||||
lcd_setline(dev, i, dev->line_length[i] - line_pos, dev->line_data[i] + line_pos);
|
||||
}
|
||||
|
||||
dev->scroll_pos++;
|
||||
|
||||
if (reset_pos == 2)
|
||||
dev->scroll_pos = -1;
|
||||
|
||||
/* disable scrolling if backlight is off (display is not visible) */
|
||||
if (dev->backlight_state == 0) {
|
||||
dev->scroll_timeout = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* periodic */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lcd_setlines(struct lcddev *dev, int scrollspeed, const char *line1, const char *line2)
|
||||
int lcd_setlines(struct lcddev *dev, int scroll_speed, const char *line1, const char *line2)
|
||||
{
|
||||
dev->line_data[0] = line1;
|
||||
lcd_setline(dev, 0, line1);
|
||||
dev->line_length[0] = (line1 != NULL) ? strlen(line1) : 0;
|
||||
lcd_setline(dev, 0, dev->line_length[0], dev->line_data[0]);
|
||||
|
||||
dev->line_data[1] = line2;
|
||||
lcd_setline(dev, 1, line2);
|
||||
dev->line_length[1] = (line2 != NULL) ? strlen(line2) : 0;
|
||||
lcd_setline(dev, 1, dev->line_length[1], dev->line_data[1]);
|
||||
|
||||
if (dev->scroll_timeout) {
|
||||
int scroll_enable = (dev->line_length[0] > 16 && dev->line_length[1] > 16);
|
||||
if (dev->scroll_timeout && ((dev->scroll_speed != scroll_speed) || !scroll_enable)) {
|
||||
event_remove_timeout(dev->scroll_timeout);
|
||||
dev->scroll_timeout = NULL;
|
||||
}
|
||||
|
||||
if (scrollspeed) {
|
||||
struct timeval tv = { .tv_usec = scrollspeed };
|
||||
dev->scroll_speed = scroll_speed;
|
||||
dev->scroll_pos = 0;
|
||||
|
||||
if ((dev->scroll_timeout == NULL) && scroll_enable && (scroll_speed > 0)) {
|
||||
struct timeval tv = { .tv_usec = 1000 * dev->scroll_speed };
|
||||
dev->scroll_timeout = event_add_timeout(&tv, lcd_scroll_timeout_cb, dev);
|
||||
}
|
||||
|
||||
@ -288,9 +357,8 @@ int lcd_setlines(struct lcddev *dev, int scrollspeed, const char *line1, const c
|
||||
}
|
||||
|
||||
struct lcddev * lcd_init(const char *devicename,
|
||||
int backlight_time,
|
||||
int (*button_cb)(struct lcddev *dev, int button, void *privdata),
|
||||
void *privdata)
|
||||
int (*event_callback)(struct lcddev *dev, int button, void *privdata),
|
||||
void *event_privdata)
|
||||
{
|
||||
struct lcddev *dev = malloc(sizeof(struct lcddev));
|
||||
if (dev == NULL) {
|
||||
@ -305,9 +373,8 @@ struct lcddev * lcd_init(const char *devicename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->backlight_time = backlight_time;
|
||||
dev->button_cb = button_cb;
|
||||
dev->privdata = privdata;
|
||||
dev->event_callback = event_callback;
|
||||
dev->event_privdata = event_privdata;
|
||||
|
||||
dev->read_event = event_add_readfd(NULL, dev->fd, lcd_read_cb, dev);
|
||||
|
||||
|
15
lcd.h
15
lcd.h
@ -1,20 +1,23 @@
|
||||
#ifndef _LCD_H_
|
||||
#define _LCD_H_
|
||||
|
||||
#define LCD_BUTTON0 0x00
|
||||
#define LCD_BUTTON1 0x01
|
||||
#define LCD_BUTTON2 0x02
|
||||
#define LCD_EVENT_INIT 0x00
|
||||
#define LCD_EVENT_BUTTON1 0x01
|
||||
#define LCD_EVENT_BUTTON2 0x02
|
||||
#define LCD_EVENT_BACKLIGHT 0x04
|
||||
|
||||
struct lcddev; /* private data */
|
||||
|
||||
struct lcddev * lcd_init(const char *device,
|
||||
int backlight_timeout,
|
||||
int (*button_callback)(struct lcddev *dev, int button, void *privdata),
|
||||
void *privdata);
|
||||
int (*event_callback)(struct lcddev *dev, int event, void *privdata),
|
||||
void *event_privdata);
|
||||
|
||||
void lcd_close(struct lcddev *dev);
|
||||
void lcd_reset(struct lcddev *dev);
|
||||
|
||||
#define LCD_BACKLIGHT_OFF (0)
|
||||
#define LCD_BACKLIGHT_ON (-1)
|
||||
|
||||
int lcd_trigger_backlight(struct lcddev *dev, int timeout);
|
||||
int lcd_setlines(struct lcddev *dev, int scrollspeed, const char *line1, const char *line2);
|
||||
|
||||
|
15
qnaplcd.c
15
qnaplcd.c
@ -54,15 +54,19 @@ static int page;
|
||||
|
||||
static int button_callback(struct lcddev *dev, int button, void *privdata)
|
||||
{
|
||||
if (button == LCD_BUTTON2)
|
||||
if (button == LCD_EVENT_BUTTON2) {
|
||||
page = (page < PAGE_MAX) ? page +1 : 0;
|
||||
|
||||
else if (button == LCD_BUTTON1)
|
||||
} else if (button == LCD_EVENT_BUTTON1) {
|
||||
page = (page > 0) ? page -1 : PAGE_MAX;
|
||||
|
||||
} else if (button == LCD_EVENT_BACKLIGHT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (page) {
|
||||
case 0:
|
||||
lcd_setlines(dev, 0, "Debian 5.0 Lenny", "2.6.34-kirkwood");
|
||||
lcd_setlines(dev, 500, "Debian GNU/Linux 5.0", "Linux 2.6.32.27-486 i586");
|
||||
break;
|
||||
case 1:
|
||||
lcd_setlines(dev, 0, "Hostname:", "storenix.lan");
|
||||
@ -87,7 +91,8 @@ static int button_callback(struct lcddev *dev, int button, void *privdata)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
lcd_trigger_backlight(dev, LCD_TIMEOUT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int restart_var;
|
||||
@ -181,7 +186,7 @@ int main(int argc, char *argv[])
|
||||
log_print(LOG_EVERYTIME, "qnaplcd started (pid:%d)", getpid());
|
||||
|
||||
while (1) {
|
||||
struct lcddev *dev = lcd_init(LCD_DEVICE, LCD_TIMEOUT, &button_callback, NULL);
|
||||
struct lcddev *dev = lcd_init(LCD_DEVICE, &button_callback, NULL);
|
||||
if (dev == NULL)
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user