summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-05-23 10:23:41 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-05-23 10:23:41 -0600
commitc7bf6bf65a458cb30b892340b69de6c025d1cc22 (patch)
treec332fd804f4cd98a1163c2e7fa246a0a58771da5 /nuttx
parentd691706b0c0fb7c2b8eeccf6f07f09fd0ecbe3fe (diff)
downloadpx4-nuttx-c7bf6bf65a458cb30b892340b69de6c025d1cc22.tar.gz
px4-nuttx-c7bf6bf65a458cb30b892340b69de6c025d1cc22.tar.bz2
px4-nuttx-c7bf6bf65a458cb30b892340b69de6c025d1cc22.zip
Add logic to encode/decode special SLCD actions
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/include/nuttx/lcd/slcd_codec.h212
-rw-r--r--nuttx/libc/Kconfig35
-rw-r--r--nuttx/libc/misc/Make.defs6
-rw-r--r--nuttx/libc/misc/lib_kbddecode.c4
-rw-r--r--nuttx/libc/misc/lib_slcddecode.c366
-rw-r--r--nuttx/libc/misc/lib_slcdencode.c203
7 files changed, 820 insertions, 12 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 54ea6a44c..93212d83e 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3819,8 +3819,8 @@
there is a issue of ARM9 systems with low vectors and large memories
that will have to be addressed in the future.
* libc/misc/lib_kbdencode.c and lib_kbddecode.c: Add logic to marshal
- and serialized "out-of-band" keyboard commands intermixed with normal
- ASCII data (not yet hooked into anything).
+ and serialize speical keyboard commands intermixed with normal ASCII
+ data (not yet hooked into anything).
* drivers/usbhost/usbhost_hidkbd.c: If CONFIG_HIDKBD_ENCODED is
defined, this driver will now use libc/misc/lib_kbdencode.c to
encode special function keys.
@@ -4779,3 +4779,5 @@
(2013-5-23)
* fs/fs_poll.c: Actually, it should not ignore invlid descriptors, it
should set the POLLNVAL event and return immediately (2013-5-23).
+ * libc/misc/lib_slcdencode.c and lib_slcddecode.c: Add logic to marshal
+ and serialized special SLCD intermixed with normal ASCII data (2013-5-23)
diff --git a/nuttx/include/nuttx/lcd/slcd_codec.h b/nuttx/include/nuttx/lcd/slcd_codec.h
new file mode 100644
index 000000000..a43796718
--- /dev/null
+++ b/nuttx/include/nuttx/lcd/slcd_codec.h
@@ -0,0 +1,212 @@
+/************************************************************************************
+ * include/nuttx/input/slcd_codec.h
+ * Serialize and marshaling data and events for character-based, segment LCDs
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_INPUT_SLCD_CODEC_H
+#define __INCLUDE_NUTTX_INPUT_SLCD_CODEC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/streams.h>
+
+#ifdef CONFIG_LIB_SLCDCODEC
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* These are the special SLCD commands recognized by the CODEC. NOTE: that
+ * some require a a count argument, N.
+ */
+
+enum slcdcode_e
+{
+ SLCDCODE_NORMAL = 0, /* Not a special keycode */
+
+ /* Delete and Backspace keycodes (in case they may be different than the
+ * ASCII BKSP and DEL values.
+ */
+
+ SLCDCODE_FWDDEL, /* DELete (forward delete) N characters moving cursor */
+ SLCDCODE_BACKDEL, /* Backspace (backward delete) N characters */
+ SLCDCODE_ERASE, /* Erase N characters from the cursor position */
+ SLCDCODE_ERASEEOL, /* Erase from the cursor position to the end of line */
+ SLCDCODE_CLEAR, /* Home the cursor and erase the entire display */
+
+ /* Cursor movement */
+
+ SLCDCODE_HOME, /* Cursor home */
+ SLCDCODE_END, /* Cursor end */
+ SLCDCODE_LEFT, /* Cursor left by N characters */
+ SLCDCODE_RIGHT, /* Cursor right by N characters */
+ SLCDCODE_UP, /* Cursor up by N lines */
+ SLCDCODE_DOWN, /* Cursor down by N lines */
+ SLCDCODE_PAGEUP, /* Cursor up by N pages */
+ SLCDCODE_PAGEDOWN, /* Cursor down by N pages */
+
+ /* Blinking */
+
+ SLCDCODE_BLINKSTART, /* Start blinking with current cursor position */
+ SLCDCODE_BLINKEND, /* End blinking after the current cursor position */
+ SLCDCODE_BLINKOFF /* Turn blinking off */
+};
+
+#define FIRST_SLCDCODE SLCDCODE_FWDDEL
+#define LAST_SLCDCODE SLCDCODE_BLINKOFF
+
+/* Values returned by slcd_decode() */
+
+enum slcdret_e
+{
+ SLCDRET_CHAR = 0, /* A normal character was returned */
+ SLCDRET_SPEC, /* A special SLCD action was returned */
+ SLCDRET_EOF /* An EOF (or possibly an error) occurred */
+};
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Working data needed by slcd_encode that must be provided and initialized
+ * by the caller.
+ */
+
+struct slcdstate_s
+{
+ uint8_t nch; /* Number of characters in the buffer */
+ uint8_t ndx; /* Index to next character in the buffer */
+ uint8_t buf[5]; /* Buffer of ungotten data */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * The following functions are intended for use by "producer", application
+ * code to encode information into driver I/O buffers.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_put
+ *
+ * Description:
+ * Put one byte of normal character data into the output data stream.
+ *
+ * Input Parameters:
+ * ch - The character to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#define slcd_put(ch, stream) (stream)->put((stream), (int)(ch))
+
+/****************************************************************************
+ * Name: slcd_encode
+ *
+ * Description:
+ * Encode one special action into the output data stream
+ *
+ * Input Parameters:
+ * code - The action to be taken
+ * count - The 8-bit unsigned count value N associated with some actions
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void slcd_encode(enum slcdcode_e code, uint8_t count,
+ FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * The following functions are intended for use by "consumer" SLCD driver
+ * code to remove and decode information from the application provided
+ * buffer.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the application provided
+ * input buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that slcd_decode is called.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * slcdcode_e, depending on the return value from slcd_decode()
+ * parg - The location to save the count argument that accompanies some
+ * special actions
+ *
+ * Returned Value:
+ *
+ * See enum slcdret_e
+ *
+ ****************************************************************************/
+
+enum slcdret_e slcd_decode(FAR struct lib_instream_s *stream,
+ FAR struct slcdstate_s *state, FAR uint8_t *pch,
+ FAR uint8_t *parg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LIB_SLCDCODEC */
+#endif /* __INCLUDE_NUTTX_INPUT_SLCD_CODEC_H */
+
diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig
index 09c332725..2173d1bd4 100644
--- a/nuttx/libc/Kconfig
+++ b/nuttx/libc/Kconfig
@@ -475,18 +475,37 @@ config LIB_KBDCODEC
may have an (optional) encoding/decoding layer on the data returned
by the character driver. A keyboard may return simple text data
(alphabetic, numeric, and punctuaction) or control characters
- (enter, control-C, etc.). We can think about this the normal
- "in-band" keyboard data stream. However, in addition, most
- keyboards support actions that cannot be represented as text data.
- Such actions include things like cursor controls (home, up arrow,
+ (enter, control-C, etc.). However, in addition, most keyboards
+ support actions that cannot be represented as text data. Such
+ actions include things like cursor controls (home, up arrow,
page down, etc.), editing functions (insert, delete, etc.), volume
- controls, (mute, volume up, etc.) and other special functions. We
- can think about this as special, "out-of-band" keyboard commands.
- In this case, some special encoding may be required to multiplex
- the in-band text data and out-of-band command streams.
+ controls, (mute, volume up, etc.) and other special functions.
+ Some special encoding may be required to multiplex these two classes
+ of data.
This option enables the functions that implement the encoding and
decoding of keyboard data. These are the interfaces prototyped in
include/nuttx/input/kbd_codec.h. While not correctly a part of
the C library, it is included here because the decoding side of this
interface must be accessible by end user programs.
+
+config LIB_SLCDCODEC
+ bool "Segment LCD CODEC"
+ default n
+ ---help---
+ In NuttX, a character-oriented, segment LCD (SLCD) driver is simply
+ a character device that may have an (optional) encoding/decoding
+ layer on the data provided to the SLCD driver. The application may
+ provide simple text data (alphabetic, numeric, and punctuaction) or
+ control characters (enter, control-C, etc.). However, in addition,
+ most SLCDs support actions that cannot be represented as text data.
+ Such actions include things like cursor controls (home, up arrow,
+ page down, etc.) and other special functions (e.g., blinking). Some
+ special encoding may be required to multiplex these two classes of
+ data.
+
+ This option enables the functions that implement the encoding and
+ decoding of SLCD data. These are the interfaces prototyped in
+ include/nuttx/lcd/slcd_codec.h. While not correctly a part of the C
+ library, it is included here because the encoding side of this
+ interface must be accessible by end user programs.
diff --git a/nuttx/libc/misc/Make.defs b/nuttx/libc/misc/Make.defs
index 0d3c87d9d..02b3b2679 100644
--- a/nuttx/libc/misc/Make.defs
+++ b/nuttx/libc/misc/Make.defs
@@ -69,6 +69,12 @@ ifeq ($(CONFIG_LIB_KBDCODEC),y)
CSRCS += lib_kbdencode.c lib_kbddecode.c
endif
+# SLCD driver encoder/decoder
+
+ifeq ($(CONFIG_LIB_SLCDCODEC),y)
+CSRCS += lib_slcdencode.c lib_slcddecode.c
+endif
+
# Add the misc directory to the build
DEPPATH += --dep-path misc
diff --git a/nuttx/libc/misc/lib_kbddecode.c b/nuttx/libc/misc/lib_kbddecode.c
index 62554902c..4e7379832 100644
--- a/nuttx/libc/misc/lib_kbddecode.c
+++ b/nuttx/libc/misc/lib_kbddecode.c
@@ -74,8 +74,8 @@
* Name: kbd_reget
*
* Description:
- * We have unused characters from the last, unsuccessful. Return one of
- * these instead of the .
+ * We have unused characters from the last, unsuccessful decode attempt.
+ * Return one of these instead of the new character from the stream.
*
* Input Parameters:
* stream - An instance of lib_instream_s to do the low-level get
diff --git a/nuttx/libc/misc/lib_slcddecode.c b/nuttx/libc/misc/lib_slcddecode.c
new file mode 100644
index 000000000..05e883f88
--- /dev/null
+++ b/nuttx/libc/misc/lib_slcddecode.c
@@ -0,0 +1,366 @@
+/****************************************************************************
+ * libc/msic/lib_slcddecode.c
+ * Decoding side of the SLCD CODEC
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/lcd/slcd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define NDX_ESC 0
+#define NDX_BRACKET 1
+#define NDX_CODE3 2
+#define NDX_COUNTH 2
+#define NDX_COUNTL 3
+#define NDX_CODE5 4
+
+#define NCH_ESC 1
+#define NCH_BRACKET 2
+#define NCH_CODE3 3
+#define NCH_COUNTH 3
+#define NCH_COUNTL 4
+#define NCH_CODE5 5
+
+#define IS_HEX(a) ((((a) >= '0') && ((a) <= '9')) || \
+ (((a) >= 'a') && ((a) <= 'f')))
+#define CODE_MIN ('A' + FIRST_SLCDCODE)
+#define CODE_MAX ('A' + LAST_SLCDCODE)
+#define IS_CODE(a) (((a) >= CODE_MIN) && ((a) <= CODE_MAX))
+#define CODE_RETURN(a) (enum slcdcode_e)((a) - 'A')
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_nibble
+ *
+ * Description:
+ * Convert a ASCII hexadecimal character (using only lower case alphabetics
+ * into a binary nibble
+ *
+ * Input Parameters:
+ * ascii - The nibble characgter.
+ *
+ * Returned Value:
+ * The binary value of the nibble.
+ *
+ ****************************************************************************/
+
+static uint8_t slcd_nibble(uint8_t ascii)
+{
+ if (ascii >= '0' && ascii <= '9')
+ {
+ return ascii - '0';
+ }
+ else
+ {
+ return ascii - 'a';
+ }
+}
+
+/****************************************************************************
+ * Name: slcd_reget
+ *
+ * Description:
+ * We have unused characters from the last, unsuccessful decode attempt.
+ * Return one of these instead of the new character from the stream.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location character to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * slcd_keycode_e
+ *
+ * Returned Value:
+ * Always SLCDRET_CHAR
+ *
+ ****************************************************************************/
+
+static enum slcdret_e slcd_reget(FAR struct slcdstate_s *state,
+ FAR uint8_t *pch, FAR uint8_t *parg)
+{
+ /* Return the next character */
+
+ *pch = state->buf[state->ndx];
+ *parg = 0;
+
+ /* Bump up the indices and return false (meaning a normal character) */
+
+ state->ndx++;
+ state->nch--;
+ return SLCDRET_CHAR;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the application provided
+ * input buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that slcd_decode is called.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * slcdcode_e, depending on the return value from slcd_decode()
+ * parg - The location to save the count argument that accompanies some
+ * special actions
+ *
+ * Returned Value:
+ *
+ * false: Normal character
+ * true: Special SLCD action code with possible argument
+ *
+ ****************************************************************************/
+
+enum slcdret_e slcd_decode(FAR struct lib_instream_s *stream,
+ FAR struct slcdstate_s *state, FAR uint8_t *pch,
+ FAR uint8_t *parg)
+
+{
+ enum slcdcode_e code;
+ uint8_t count;
+ int ch;
+
+ DEBUGASSERT(stream && state && pch && parg);
+
+ /* Are their ungotten characters from the last, failed parse? */
+
+ if (state->nch > 0)
+ {
+ /* Yes, return the next ungotten character */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ state->ndx = 0;
+
+ /* No, ungotten characters. Get the next character from the buffer. */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream (or perhaps an I/O error) */
+
+ return SLCDRET_EOF;
+ }
+
+ /* Save the character (whatever it is) in case we fail parsing later */
+
+ state->buf[NDX_ESC] = (uint8_t)ch;
+ state->nch = NCH_ESC;
+
+ /* Check for the beginning of an escape sequence */
+
+ if (ch != ASCII_ESC)
+ {
+ /* Not the beginning of an escape sequence. Return the character. */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Get the next character from the buffer */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the escape character now. We will
+ * return the EOF indication next time.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Save the character (whatever it is) in case we fail parsing later */
+
+ state->buf[NDX_BRACKET] = ch;
+ state->nch = NCH_BRACKET;
+
+ /* Check for ESC-[ */
+
+ if (ch != '[')
+ {
+ /* Not the beginning of an escape sequence. Return the ESC now,
+ * return the following characters later.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Get the next character from the buffer */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the ESC now; return the following
+ * characters later.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* If the next character is a hexidecimal value (with lower case
+ * alphabetic characters), then we are parsing a 5-byte sequence.
+ */
+
+ if (!IS_HEX(ch))
+ {
+ /* Verify the special CLCD action code */
+
+ if (ch < (int)FIRST_SLCDCODE || ch > (int)LAST_SLCDCODE)
+ {
+ /* Not a special command code.. put the character in the reget
+ * buffer.
+ */
+
+ state->buf[NDX_CODE3] = (uint8_t)ch;
+ state->nch = NCH_CODE3;
+
+ /* Return the ESC now and the next two characters later. */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Provide the return values */
+
+ code = CODE_RETURN(ch);
+ count = 0;
+ }
+ else
+ {
+ /* Save the first character of the two byte hexidecimal number */
+
+ state->buf[NDX_COUNTH] = (uint8_t)ch;
+ state->nch = NCH_COUNTH;
+
+ /* Get the next character from the buffer */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the ESC now; return the following
+ * characters later.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* We expect the next character to be the second byte of hexidecimal
+ * count value.
+ */
+
+ if (!IS_HEX(ch))
+ {
+ /* Not a 5-byte escape sequence. Return the ESC now; return the
+ * following characters later.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Save the second character of the two byte hexidecimal number */
+
+ state->buf[NDX_COUNTL] = (uint8_t)ch;
+ state->nch = NCH_COUNTL;
+
+ /* Get the next character from the buffer */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the ESC now; return the following
+ * characters later.
+ */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Verify the special CLCD action code */
+
+ if (ch < (int)FIRST_SLCDCODE || ch > (int)LAST_SLCDCODE)
+ {
+ /* Not a special command code.. put the character in the reget
+ * buffer.
+ */
+
+ state->buf[NDX_CODE5] = (uint8_t)ch;
+ state->nch = NCH_CODE5;
+
+ /* Return the ESC now and the next two characters later. */
+
+ return slcd_reget(state, pch, parg);
+ }
+
+ /* Provide the return values */
+
+ code = CODE_RETURN(ch);
+ count = slcd_nibble(state->buf[NDX_COUNTH]) << 4;
+ slcd_nibble(state->buf[NDX_COUNTL]);
+ }
+
+ /* We have successfully parsed the the entire escape sequence. Return the
+ * CLCD value in pch, return the count in parg, and an indication that this
+ * is a special action.
+ */
+
+ *pch = code;
+ *parg = count;
+ state->nch = 0;
+ return SLCDRET_SPEC;
+}
+
diff --git a/nuttx/libc/misc/lib_slcdencode.c b/nuttx/libc/misc/lib_slcdencode.c
new file mode 100644
index 000000000..148cb3a99
--- /dev/null
+++ b/nuttx/libc/misc/lib_slcdencode.c
@@ -0,0 +1,203 @@
+/****************************************************************************
+ * libc/msic/lib_slcdencode.c
+ * Encoding side of the SLCD CODEC
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/lcd/slcd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_nibble
+ *
+ * Description:
+ * Convert a binary nibble to a hexadecimal character (using only lower
+ * case alphabetics).
+ *
+ * Input Parameters:
+ * binary - The nibble value.
+ *
+ * Returned Value:
+ * The ASCII hexadecimal character representing the nibble.
+ *
+ ****************************************************************************/
+
+static uint8_t slcd_nibble(uint8_t binary)
+{
+ binary &= 0x0f;
+
+ if (binary > 9)
+ {
+ return '0' + binary;
+ }
+ else
+ {
+ return 'a' + binary;
+ }
+}
+
+/****************************************************************************
+ * Name: slcd_put3
+ *
+ * Description:
+ * Encode one special special 3-byte sequence command into the output
+ * stream.
+ *
+ * Input Parameters:
+ * slcdcode - The special action to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void slcd_put3(uint8_t slcdcode,
+ FAR struct lib_outstream_s *stream)
+{
+ /* Put the 3-byte escape sequences into the output buffer */
+
+ stream->put(stream, ASCII_ESC);
+ stream->put(stream, '[');
+ stream->put(stream, 'A' + (int)slcdcode);
+}
+
+/****************************************************************************
+ * Name: slcd_putarg
+ *
+ * Description:
+ * Encode one special special 5-byte sequence command into the output
+ * stream.
+ *
+ * Input Parameters:
+ * slcdcode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ * terminator - Escape sequence terminating character.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+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);
+ stream->put(stream, '[');
+ stream->put(stream, slcd_nibble(count >> 4));
+ stream->put(stream, slcd_nibble(count));
+ stream->put(stream, 'A' + (int)slcdcode);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slcd_encode
+ *
+ * Description:
+ * Encode one special action into the output data stream
+ *
+ * Input Parameters:
+ * code - The action to be taken
+ * count - The count value N associated with some actions
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void slcd_encode(enum slcdcode_e code, uint8_t count,
+ FAR struct lib_outstream_s *stream)
+{
+ switch (code)
+ {
+ /* Codes with no argument */
+
+ case SLCDCODE_ERASEEOL: /* Erase from the cursor position to the end of line */
+ case SLCDCODE_CLEAR: /* Home the cursor and erase the entire display */
+ case SLCDCODE_HOME: /* Cursor home */
+ case SLCDCODE_END: /* Cursor end */
+ case SLCDCODE_BLINKSTART: /* Start blinking with current cursor position */
+ case SLCDCODE_BLINKEND: /* End blinking after the current cursor position */
+ case SLCDCODE_BLINKOFF: /* Turn blinking off */
+ slcd_put3(code, stream); /* Generate the 3-byte encoding */
+ break;
+
+ /* Codes with an 8-bit count argument */
+
+ case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving cursor */
+ case SLCDCODE_BACKDEL: /* Backspace (backward delete) N characters */
+ case SLCDCODE_ERASE: /* Erase N characters from the cursor position */
+ case SLCDCODE_LEFT: /* Cursor left by N characters */
+ case SLCDCODE_RIGHT: /* Cursor right by N characters */
+ case SLCDCODE_UP: /* Cursor up by N lines */
+ case SLCDCODE_DOWN: /* Cursor down by N lines */
+ case SLCDCODE_PAGEUP: /* Cursor up by N pages */
+ case SLCDCODE_PAGEDOWN: /* Cursor down by N pages */
+ slcd_put5(code, count, stream); /* Generate the 5-byte sequence */
+ break;
+
+ default:
+ case SLCDCODE_NORMAL: /* Not a special slcdcode */
+ break;
+ }
+}