diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-05-26 11:26:34 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-05-26 11:26:34 -0600 |
commit | 5049717590dea3c2bb216409887eff9ec4f2d535 (patch) | |
tree | 96c58ccbab729b3c51fe31ad3a728f00f819ae9b | |
parent | 5e23e42a0d5f7256bb284bdd8ffbe7b52eef0cef (diff) | |
download | nuttx-5049717590dea3c2bb216409887eff9ec4f2d535.tar.gz nuttx-5049717590dea3c2bb216409887eff9ec4f2d535.tar.bz2 nuttx-5049717590dea3c2bb216409887eff9ec4f2d535.zip |
More SLCD-related fixes
-rw-r--r-- | apps/examples/slcd/slcd_main.c | 37 | ||||
-rw-r--r-- | nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c | 255 | ||||
-rw-r--r-- | nuttx/configs/stm32ldiscovery/src/stm32_lcd.c | 182 | ||||
-rw-r--r-- | nuttx/libc/misc/lib_slcddecode.c | 6 | ||||
-rw-r--r-- | nuttx/libc/misc/lib_slcdencode.c | 7 |
5 files changed, 304 insertions, 183 deletions
diff --git a/apps/examples/slcd/slcd_main.c b/apps/examples/slcd/slcd_main.c index b6168de56..604ac6c28 100644 --- a/apps/examples/slcd/slcd_main.c +++ b/apps/examples/slcd/slcd_main.c @@ -250,6 +250,7 @@ int slcd_main(int argc, char *argv[]) { FAR struct slcd_test_s *priv = &g_slcdtest; FAR const char *str = g_slcdhello; + int fd; int ret; /* Parse the command line. For now, only a single optional string argument @@ -261,11 +262,22 @@ int slcd_main(int argc, char *argv[]) { str = argv[1]; } +#endif + + /* Open the SLCD device */ + + printf("Opening %s for read/write access\n", CONFIG_EXAMPLES_SLCD_DEVNAME); + + fd = open(CONFIG_EXAMPLES_SLCD_DEVNAME, O_RDWR); + if (priv->fd < 0) + { + printf("Failed to open %s: %d\n", CONFIG_EXAMPLES_SLCD_DEVNAME, errno); + goto errout; + } /* Are we already initialized? */ if (!priv->initialized) -#endif { /* Initialize the output stream */ @@ -275,20 +287,9 @@ int slcd_main(int argc, char *argv[]) priv->stream.flush = slcd_flush; #endif - /* Open the SLCD device */ - - printf("Opening %s for read/write access\n", CONFIG_EXAMPLES_SLCD_DEVNAME); - - priv->fd = open(CONFIG_EXAMPLES_SLCD_DEVNAME, O_RDWR); - if (priv->fd < 0) - { - printf("Failed to open %s: %d\n", CONFIG_EXAMPLES_SLCD_DEVNAME, errno); - goto errout; - } - /* Get the geometry of the SCLD device */ - ret = ioctl(priv->fd, SLCDIOC_GEOMETRY, (unsigned long)&priv->geo); + ret = ioctl(fd, SLCDIOC_GEOMETRY, (unsigned long)&priv->geo); if (ret < 0) { printf("ioctl(SLCDIOC_GEOMETRY) failed: %d\n", errno); @@ -307,8 +308,12 @@ int slcd_main(int argc, char *argv[]) priv->initialized = true; } - /* Set the cursor to the beginning of the current row and erase to the end - * of the line. + /* Save the file descriptor in a place where slcd_flush can find it */ + + priv->fd = fd; + + /* Set the cursor to the beginning of the current row by homing the cursor + * then going down as necessary, and erase to the end of the line. */ slcd_encode(SLCDCODE_HOME, 0, &priv->stream); @@ -331,7 +336,7 @@ int slcd_main(int argc, char *argv[]) /* Normal exit */ printf("Test complete\n"); - close(priv->fd); + close(fd); return 0; errout_with_fd: diff --git a/nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c b/nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c index 50697c587..bf564cf96 100644 --- a/nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c +++ b/nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c @@ -116,7 +116,17 @@ # undef CONFIG_DEBUG_LCD #endif -/* Pin configuratin *********************************************************/ +/* The ever-present MIN/MAX macros ******************************************/ + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +/* Pin configuration ********************************************************/ /* RB15, RS -- High values selects data */ #define GPIO_LCD_RS (GPIO_OUTPUT|GPIO_VALUE_ZERO|GPIO_PORTB|GPIO_PIN15) @@ -166,8 +176,11 @@ struct lcd1602_2 #if defined(CONFIG_DEBUG_LCD) && defined(CONFIG_DEBUG_VERBOSE) static void lcd_dumpstate(FAR const char *msg); +static void lcd_dumpstream(FAR const char *msg, + FAR const struct lcd_instream_s *stream); #else # define lcd_dumpstate(msg) +# define lcd_dumpstream(msg, stream) #endif /* Internal functions */ @@ -253,6 +266,21 @@ static void lcd_dumpstate(FAR const char *msg) #endif /**************************************************************************** + * Name: lcd_dumpstate + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_LCD) && defined(CONFIG_DEBUG_VERBOSE) +static void lcd_dumpstream(FAR const char *msg, + FAR const struct lcd_instream_s *stream) +{ + lcdvdbg("%s:\n", msg); + lcdvdbg(" nget: %d nbytes: %d\n", + stream->stream.nget, stream->nbytes); + lib_dumpbuffer("STREAM", stream->buffer, stream->nbytes); +} +#endif + +/**************************************************************************** * Name: lcd_getstream * * Description: @@ -418,61 +446,86 @@ static void lcd_action(enum slcdcode_e code, uint8_t count) case SLCDCODE_BACKDEL: /* Backspace (backward delete) N characters */ { - /* If we are at the home position, then ignore the action */ + int tmp; + + /* If we are at the home position or if the count is zero, then ignore the action */ - if (g_lcd1602.curcol < 1) + if (g_lcd1602.curcol < 1 || count < 1) { break; } - /* Otherwise, BACKDEL is like moving the cursor back one then doing a + /* Otherwise, BACKDEL is like moving the cursor back N characters then doing a * forward deletion. Decrement the cursor position and fall through. */ - g_lcd1602.curcol--; - } + tmp = (int)g_lcd1602.curcol - count; + if (tmp < 0) + { + tmp = 0; + count = g_lcd1602.curcol; + } - case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */ - { - uint8_t ch; - int i; + /* Save the updated cursor positions */ - /* Move all characters after the current cursor position left by one */ - - for (i = g_lcd1602.curcol + 1; i < LCD_NCOLUMNS - 1; i++) - { - ch = lcd_readch(g_lcd1602.currow, i); - lcd_writech(ch, g_lcd1602.currow, i - 1); - } - - /* Erase the last character on the display */ + g_lcd1602.curcol = tmp; + } - lcd_writech(' ', g_lcd1602.currow, LCD_NCOLUMNS - 1); - } + case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */ + if (count > 0) + { + int nchars; + int nmove; + int i; + + /* How many characters are to the right of the cursor position + * (including the one at the cursor position)? Then get the + * number of characters to move. + */ + + nchars = LCD_NCOLUMNS - g_lcd1602.curcol; + nmove = MIN(nchars, count) - 1; + + /* Move all characters after the current cursor position left by 'nmove' characters */ + + for (i = g_lcd1602.curcol + nmove; i < LCD_NCOLUMNS - 1; i++) + { + uint8_t ch = lcd_readch(g_lcd1602.currow, i); + lcd_writech(ch, g_lcd1602.currow, i - nmove); + } + + /* Erase the last 'nmove' characters on the display */ + + for (i = LCD_NCOLUMNS - nmove; i < LCD_NCOLUMNS; i++) + { + lcd_writech(' ', i, 0); + } + } break; case SLCDCODE_ERASE: /* Erase N characters from the cursor position */ - { - int last; - int i; - - /* Get the last position to clear and make sure that the last - * position is on the SLCD. - */ - - last = g_lcd1602.curcol + count - 1; - if (last >= LCD_NCOLUMNS) - { - last = LCD_NCOLUMNS - 1; - } - - /* Erase N characters after the current cursor position left by one */ - - for (i = g_lcd1602.curcol; i < last; i++) - { - lcd_writech(' ', g_lcd1602.currow, i); - } - } + if (count > 0) + { + int last; + int i; + + /* Get the last position to clear and make sure that the last + * position is on the SLCD. + */ + + last = g_lcd1602.curcol + count - 1; + if (last >= LCD_NCOLUMNS) + { + last = LCD_NCOLUMNS - 1; + } + + /* Erase N characters after the current cursor position left by one */ + + for (i = g_lcd1602.curcol; i < last; i++) + { + lcd_writech(' ', g_lcd1602.currow, i); + } + } break; case SLCDCODE_CLEAR: /* Home the cursor and erase the entire display */ @@ -518,45 +571,69 @@ static void lcd_action(enum slcdcode_e code, uint8_t count) case SLCDCODE_LEFT: /* Cursor left by N characters */ { + int tmp = (int)g_lcd1602.curcol - count; + /* Don't permit movement past the beginning of the SLCD */ - if (g_lcd1602.curcol > 0) + if (tmp < 0) { - g_lcd1602.curcol--; + tmp = 0; } + + /* Save the new cursor position */ + + g_lcd1602.curcol = (uint8_t)tmp; } break; case SLCDCODE_RIGHT: /* Cursor right by N characters */ { + int tmp = (int)g_lcd1602.curcol + count; + /* Don't permit movement past the end of the SLCD */ - if (g_lcd1602.curcol < (LCD_NCOLUMNS - 1)) + if (tmp >= LCD_NCOLUMNS) { - g_lcd1602.curcol++; + tmp = LCD_NCOLUMNS - 1; } + + /* Save the new cursor position */ + + g_lcd1602.curcol = (uint8_t)tmp; } break; case SLCDCODE_UP: /* Cursor up by N lines */ { + int tmp = (int)g_lcd1602.currow - count; + /* Don't permit movement past the top of the SLCD */ - if (g_lcd1602.currow > 0) + if (tmp < 0) { - g_lcd1602.currow--; + tmp = 0; } + + /* Save the new cursor position */ + + g_lcd1602.currow = (uint8_t)tmp; } break; case SLCDCODE_DOWN: /* Cursor down by N lines */ { + int tmp = (int)g_lcd1602.currow + count; + /* Don't permit movement past the bottom of the SLCD */ - if (g_lcd1602.currow < (LCD_NCOLUMNS - 1)) + if (tmp >= LCD_NROWS) { - g_lcd1602.currow++; + tmp = LCD_NROWS - 1; } + + /* Save the new cursor position */ + + g_lcd1602.currow = (uint8_t)tmp; } break; @@ -627,8 +704,6 @@ static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, enum slcdret_e result; uint8_t ch; uint8_t count; - uint8_t prev = ' '; - bool valid = false; /* Initialize the stream for use with the SLCD CODEC */ @@ -637,33 +712,11 @@ static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, instream.buffer = buffer; instream.nbytes = len; - /* Prime the pump */ - - memset(&state, 0, sizeof(struct slcdstate_s)); - result = slcd_decode(&instream.stream, &state, &prev, &count); - - lcdvdbg("slcd_decode returned result=%d char=%d count=%d\n", - result, prev, count); - - switch (result) - { - case SLCDRET_CHAR: - valid = true; - break; - - case SLCDRET_SPEC: - { - lcd_action((enum slcdcode_e)prev, count); - prev = ' '; - } - break; - - case SLCDRET_EOF: - return 0; - } + lcd_dumpstream("BEFORE WRITE", &instream); /* Now decode and process every byte in the input buffer */ + memset(&state, 0, sizeof(struct slcdstate_s)); while ((result = slcd_decode(&instream.stream, &state, &ch, &count)) != SLCDRET_EOF) { lcdvdbg("slcd_decode returned result=%d char=%d count=%d\n", @@ -679,37 +732,25 @@ static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, if (ch == ASCII_BS) { + /* Perform the backward deletion */ + lcd_action(SLCDCODE_BACKDEL, 1); } else if (ch == ASCII_CR) { - lcd_action(SLCDCODE_HOME, 0); - } - } - - /* Handle characters decoreated with a period or a colon */ + /* Perform the carriage return */ - else if (ch == '.') - { - /* Write the previous character with the decimal point appended */ - - lcd_appendch(prev); - prev = ' '; - valid = false; - } - else if (ch == ':') - { - /* Write the previous character with the colon appended */ - - lcd_appendch(prev); - prev = ' '; - valid = false; + g_lcd1602.curcol = 0; + lcd_action(SLCDCODE_DOWN, 1); + } } /* Handle ASCII_DEL */ else if (ch == ASCII_DEL) { + /* Perform the forward deletion */ + lcd_action(SLCDCODE_FWDDEL, 1); } @@ -717,34 +758,22 @@ static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, else if (ch < 128) { - /* Write the previous character if it valid */ - - if (valid) - { - lcd_appendch(prev); - } - - /* There is now a valid output character */ + /* Write the character if it valid */ - prev = ch; - valid = true; + lcd_appendch(ch); } } else /* (result == SLCDRET_SPEC) */ /* A special SLCD action was returned */ { + /* Then Perform the action */ + lcd_action((enum slcdcode_e)ch, count); } } - /* Handle any unfinished output */ - - if (valid) - { - lcd_appendch(prev); - } - /* Assume that the entire input buffer was processed */ + lcd_dumpstream("AFTER WRITE", &instream); return (ssize_t)len; } diff --git a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c index abc9a0644..d843fba7e 100644 --- a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c +++ b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c @@ -94,6 +94,8 @@ # undef CONFIG_DEBUG_LCD #endif +/* The ever-present MIN/MAX macros ******************************************/ + #ifndef MIN # define MIN(a,b) (a < b ? a : b) #endif @@ -896,59 +898,85 @@ static void slcd_action(enum slcdcode_e code, uint8_t count) case SLCDCODE_BACKDEL: /* Backspace (backward delete) N characters */ { - /* If we are at the home position, then ignore the action */ + int tmp; + + /* If we are at the home position or if the count is zero, then ignore the action */ - if (g_slcdstate.curpos < 1) + if (g_slcdstate.curpos < 1 || count < 1) { break; } - /* Otherwise, BACKDEL is like moving the cursor back one then doing a + /* Otherwise, BACKDEL is like moving the cursor back N characters then doing a * forward deletion. Decrement the cursor position and fall through. */ - g_slcdstate.curpos--; - } - - case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */ - { - int i; - - /* Move all characters after the current cursor position left by one */ + tmp = (int)g_slcdstate.curpos - count; + if (tmp < 0) + { + tmp = 0; + count = g_slcdstate.curpos; + } - for (i = g_slcdstate.curpos + 1; i < SLCD_NCHARS - 1; i++) - { - slcd_writech(g_slcdstate.buffer[i-1], i, g_slcdstate.options[i-1]); - } + /* Save the updated cursor positions */ - /* Erase the last character on the display */ + g_slcdstate.curpos = tmp; + } - slcd_writech(' ', SLCD_NCHARS - 1, 0); - } + case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */ + if (count > 0) + { + int nchars; + int nmove; + int i; + + /* How many characters are to the right of the cursor position + * (including the one at the cursor position)? Then get the + * number of characters to move. + */ + + nchars = SLCD_CHARS - g_slcdstate.curpos; + nmove = MIN(nchars, count) - 1; + + /* Move all characters after the current cursor position left by 'nmove' characters */ + + for (i = g_slcdstate.curpos + nmove; i < SLCD_NCHARS - 1; i++) + { + slcd_writech(g_slcdstate.buffer[i-nmove], i, g_slcdstate.options[i-nmove]); + } + + /* Erase the last 'nmove' characters on the display */ + + for (i = SLCD_NCHARS - nmove; i < SLCD_NCHARS; i++) + { + slcd_writech(' ', i, 0); + } + } break; case SLCDCODE_ERASE: /* Erase N characters from the cursor position */ - { - int last; - int i; - - /* Get the last position to clear and make sure that the last - * position is on the SLCD. - */ - - last = g_slcdstate.curpos + count - 1; - if (last >= SLCD_NCHARS) - { - last = SLCD_NCHARS - 1; - } - - /* Erase N characters after the current cursor position left by one */ - - for (i = g_slcdstate.curpos; i < last; i++) - { - slcd_writech(' ', i, 0); - } - } + if (count > 0) + { + int last; + int i; + + /* Get the last position to clear and make sure that the last + * position is on the SLCD. + */ + + last = g_slcdstate.curpos + count - 1; + if (last >= SLCD_NCHARS) + { + last = SLCD_NCHARS - 1; + } + + /* Erase N characters after the current cursor position left by one */ + + for (i = g_slcdstate.curpos; i < last; i++) + { + slcd_writech(' ', i, 0); + } + } break; case SLCDCODE_CLEAR: /* Home the cursor and erase the entire display */ @@ -989,23 +1017,35 @@ static void slcd_action(enum slcdcode_e code, uint8_t count) case SLCDCODE_LEFT: /* Cursor left by N characters */ { + int tmp = (int)g_slcdstate.curpos - count; + /* Don't permit movement past the beginning of the SLCD */ - if (g_slcdstate.curpos > 0) + if (tmp < 0) { - g_slcdstate.curpos--; + tmp = 0; } + + /* Save the new cursor position */ + + g_slcdstate.curpos = (uint8_t)tmp; } break; case SLCDCODE_RIGHT: /* Cursor right by N characters */ { + int tmp = (int)g_slcdstate.curpos + count; + /* Don't permit movement past the end of the SLCD */ - if (g_slcdstate.curpos < (SLCD_NCHARS - 1)) + if (tmp >= SLCD_NCHARS) { - g_slcdstate.curpos++; + tmp = SLCD_NCHARS - 1; } + + /* Save the new cursor position */ + + g_slcdstate.curpos = (uint8_t)tmp; } break; @@ -1096,7 +1136,9 @@ static ssize_t slcd_write(FAR struct file *filp, instream.buffer = buffer; instream.nbytes = len; - /* Prime the pump */ + /* Prime the pump. This is messy, but necessary to handle decoration on a + * character based on any following period or colon. + */ memset(&state, 0, sizeof(struct slcdstate_s)); result = slcd_decode(&instream.stream, &state, &prev, &count); @@ -1138,10 +1180,36 @@ static ssize_t slcd_write(FAR struct file *filp, if (ch == ASCII_BS) { + /* If there is a pending character, then output it now before + * performing the action. + */ + + if (valid) + { + slcd_appendch(prev, 0); + prev = ' '; + valid = false; + } + + /* Then perform the backward deletion */ + slcd_action(SLCDCODE_BACKDEL, 1); } else if (ch == ASCII_CR) { + /* If there is a pending character, then output it now before + * performing the action. + */ + + if (valid) + { + slcd_appendch(prev, 0); + prev = ' '; + valid = false; + } + + /* Then perform the carriage return */ + slcd_action(SLCDCODE_HOME, 0); } } @@ -1169,6 +1237,19 @@ static ssize_t slcd_write(FAR struct file *filp, else if (ch == ASCII_DEL) { + /* If there is a pending character, then output it now before + * performing the action. + */ + + if (valid) + { + slcd_appendch(prev, 0); + prev = ' '; + valid = false; + } + + /* Then perform the foward deletion */ + slcd_action(SLCDCODE_FWDDEL, 1); } @@ -1191,6 +1272,19 @@ static ssize_t slcd_write(FAR struct file *filp, } else /* (result == SLCDRET_SPEC) */ /* A special SLCD action was returned */ { + /* If there is a pending character, then output it now before + * performing the action. + */ + + if (valid) + { + slcd_appendch(prev, 0); + prev = ' '; + valid = false; + } + + /* Then perform the action */ + slcd_action((enum slcdcode_e)ch, count); } } diff --git a/nuttx/libc/misc/lib_slcddecode.c b/nuttx/libc/misc/lib_slcddecode.c index 79c549b39..7a413c02c 100644 --- a/nuttx/libc/misc/lib_slcddecode.c +++ b/nuttx/libc/misc/lib_slcddecode.c @@ -378,14 +378,14 @@ enum slcdret_e slcd_decode(FAR struct lib_instream_s *stream, /* Verify the special CLCD action code */ - if (code < (int)FIRST_SLCDCODE || code > (int)LAST_SLCDCODE || count < 1) + if (code < (int)FIRST_SLCDCODE || code > (int)LAST_SLCDCODE) { /* Not a special command code. Return the ESC now and the rest * of the characters later. */ - lcddbg("Parsing failed: ESC-L-%c-%c followed by %02x, count=%d\n", - state->buf[NDX_COUNTH], state->buf[NDX_COUNTL], ch, count); + lcddbg("Parsing failed: ESC-L-%c-%c followed by %02x\n", + state->buf[NDX_COUNTH], state->buf[NDX_COUNTL], ch); return slcd_reget(state, pch, parg); } diff --git a/nuttx/libc/misc/lib_slcdencode.c b/nuttx/libc/misc/lib_slcdencode.c index 12454ca8e..b239873fb 100644 --- a/nuttx/libc/misc/lib_slcdencode.c +++ b/nuttx/libc/misc/lib_slcdencode.c @@ -128,13 +128,6 @@ static inline void slcd_put3(uint8_t slcdcode, static inline void slcd_put5(uint8_t slcdcode, uint8_t count, FAR struct lib_outstream_s *stream) { - /* The minimum value of the count argument is one */ - - if (count < 1) - { - count = 1; - } - /* Put the 5-byte escape sequences into the output buffer */ stream->put(stream, ASCII_ESC); |