summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/examples/slcd/slcd_main.c37
-rw-r--r--nuttx/configs/pcblogic-pic32mx/src/pic32mx_lcd1602.c255
-rw-r--r--nuttx/configs/stm32ldiscovery/src/stm32_lcd.c182
-rw-r--r--nuttx/libc/misc/lib_slcddecode.c6
-rw-r--r--nuttx/libc/misc/lib_slcdencode.c7
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);