More SLCD-related fixes
This commit is contained in:
parent
e0e60eae7b
commit
916ec62df3
@ -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 */
|
||||
@ -252,6 +265,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
|
||||
*
|
||||
@ -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 (g_lcd1602.curcol < 1)
|
||||
/* If we are at the home position or if the count is zero, then ignore the action */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Save the updated cursor positions */
|
||||
|
||||
g_lcd1602.curcol = tmp;
|
||||
}
|
||||
|
||||
case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */
|
||||
{
|
||||
uint8_t ch;
|
||||
int i;
|
||||
if (count > 0)
|
||||
{
|
||||
int nchars;
|
||||
int nmove;
|
||||
int i;
|
||||
|
||||
/* Move all characters after the current cursor position left by one */
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
nchars = LCD_NCOLUMNS - g_lcd1602.curcol;
|
||||
nmove = MIN(nchars, count) - 1;
|
||||
|
||||
/* Erase the last character on the display */
|
||||
/* Move all characters after the current cursor position left by 'nmove' characters */
|
||||
|
||||
lcd_writech(' ', g_lcd1602.currow, LCD_NCOLUMNS - 1);
|
||||
}
|
||||
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;
|
||||
if (count > 0)
|
||||
{
|
||||
int last;
|
||||
int i;
|
||||
|
||||
/* Get the last position to clear and make sure that the last
|
||||
* position is on the SLCD.
|
||||
*/
|
||||
/* 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;
|
||||
}
|
||||
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 */
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
/* Perform the carriage return */
|
||||
|
||||
g_lcd1602.curcol = 0;
|
||||
lcd_action(SLCDCODE_DOWN, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle characters decoreated with a period or a colon */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* Write the character if it valid */
|
||||
|
||||
if (valid)
|
||||
{
|
||||
lcd_appendch(prev);
|
||||
}
|
||||
|
||||
/* There is now a valid output character */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 (g_slcdstate.curpos < 1)
|
||||
/* If we are at the home position or if the count is zero, then ignore the action */
|
||||
|
||||
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--;
|
||||
tmp = (int)g_slcdstate.curpos - count;
|
||||
if (tmp < 0)
|
||||
{
|
||||
tmp = 0;
|
||||
count = g_slcdstate.curpos;
|
||||
}
|
||||
|
||||
/* Save the updated cursor positions */
|
||||
|
||||
g_slcdstate.curpos = tmp;
|
||||
}
|
||||
|
||||
case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */
|
||||
{
|
||||
int i;
|
||||
if (count > 0)
|
||||
{
|
||||
int nchars;
|
||||
int nmove;
|
||||
int i;
|
||||
|
||||
/* Move all characters after the current cursor position left by one */
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
for (i = g_slcdstate.curpos + 1; i < SLCD_NCHARS - 1; i++)
|
||||
{
|
||||
slcd_writech(g_slcdstate.buffer[i-1], i, g_slcdstate.options[i-1]);
|
||||
}
|
||||
nchars = SLCD_CHARS - g_slcdstate.curpos;
|
||||
nmove = MIN(nchars, count) - 1;
|
||||
|
||||
/* Erase the last character on the display */
|
||||
/* Move all characters after the current cursor position left by 'nmove' characters */
|
||||
|
||||
slcd_writech(' ', SLCD_NCHARS - 1, 0);
|
||||
}
|
||||
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;
|
||||
if (count > 0)
|
||||
{
|
||||
int last;
|
||||
int i;
|
||||
|
||||
/* Get the last position to clear and make sure that the last
|
||||
* position is on the SLCD.
|
||||
*/
|
||||
/* 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;
|
||||
}
|
||||
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 */
|
||||
/* Erase N characters after the current cursor position left by one */
|
||||
|
||||
for (i = g_slcdstate.curpos; i < last; i++)
|
||||
{
|
||||
slcd_writech(' ', i, 0);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user