The SAM4L Xplained Pro SLCD driver is code complete but untested

This commit is contained in:
Gregory Nutt 2013-06-22 10:39:25 -06:00
parent d7ec0089a7
commit 7b716cf8f5
4 changed files with 359 additions and 222 deletions

View File

@ -679,77 +679,104 @@ Configuration sub-directories
This configuration directory will built the NuttShell. See NOTES above This configuration directory will built the NuttShell. See NOTES above
and below: and below:
NOTE: NOTES:
If the I/O1 module is connected to the SAM4L Xplained Pro, then support
for the SD card slot can be enabled by making the following changes
to the configuration:
File Systems: 1. If the I/O1 module is connected to the SAM4L Xplained Pro, then
CONFIG_FS_FAT=y : Enable the FAT file system support for the SD card slot can be enabled by making the following
CONFIG_FAT_LCNAMES=y : Enable upper/lower case 8.3 file names (Optional, see below) changes to the configuration:
CONFIG_FAT_LFN=y : Enable long file named (Optional, see below)
CONFIG_FAT_MAXFNAME=32 : Maximum supported file name length
There are issues related to patents that Microsoft holds on FAT long File Systems:
file name technologies. See the top level COPYING file for further CONFIG_FS_FAT=y : Enable the FAT file system
details. CONFIG_FAT_LCNAMES=y : Enable upper/lower case 8.3 file names (Optional, see below)
CONFIG_FAT_LFN=y : Enable long file named (Optional, see below)
CONFIG_FAT_MAXFNAME=32 : Maximum supported file name length
System Type -> Peripherals: There are issues related to patents that Microsoft holds on FAT long
CONFIG_SAM34_SPI=y : Enable the SAM4L SPI peripheral file name technologies. See the top level COPYING file for further
details.
Device Drivers System Type -> Peripherals:
CONFIG_SPI=y : Enable SPI support CONFIG_SAM34_SPI=y : Enable the SAM4L SPI peripheral
CONFIG_SPI_EXCHANGE=y : The exchange() method is supported
CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device
CONFIG_MMCSD=y : Enable MMC/SD support Device Drivers
CONFIG_MMCSD_NSLOTS=1 : Only one MMC/SD card slot CONFIG_SPI=y : Enable SPI support
CONFIG_MMCSD_MULTIBLOCK_DISABLE=n : Should not need to disable multi-block transfers CONFIG_SPI_EXCHANGE=y : The exchange() method is supported
CONFIG_MMCSD_HAVECARDDETECT=y : I/O1 module as a card detect GPIO CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device
CONFIG_MMCSD_SPI=y : Use the SPI interface to the MMC/SD card
CONFIG_MMCSD_SPICLOCK=20000000 : This is a guess for the optimal MMC/SD frequency
CONFIG_MMCSD_SPIMODE=0 : Mode 0 is required
Board Selection -> Common Board Options CONFIG_MMCSD=y : Enable MMC/SD support
CONFIG_NSH_MMCSDSLOTNO=0 : Only one MMC/SD slot, slot 0 CONFIG_MMCSD_NSLOTS=1 : Only one MMC/SD card slot
CONFIG_NSH_MMCSDSPIPORTNO=0 : Use CS=0 if the I/O1 is in EXT1, OR CONFIG_MMCSD_MULTIBLOCK_DISABLE=n : Should not need to disable multi-block transfers
CONFIG_NSH_MMCSDSPIPORTNO=2 : Use CS=2 if the I/O1 is in EXT2 CONFIG_MMCSD_HAVECARDDETECT=y : I/O1 module as a card detect GPIO
CONFIG_MMCSD_SPI=y : Use the SPI interface to the MMC/SD card
CONFIG_MMCSD_SPICLOCK=20000000 : This is a guess for the optimal MMC/SD frequency
CONFIG_MMCSD_SPIMODE=0 : Mode 0 is required
Board Selection -> SAM4L Xplained Pro Modules Board Selection -> Common Board Options
CONFIG_SAM4L_XPLAINED_IOMODULE=y : I/O1 module is connected CONFIG_NSH_MMCSDSLOTNO=0 : Only one MMC/SD slot, slot 0
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT1=y : In EXT1, or EXT2 CONFIG_NSH_MMCSDSPIPORTNO=0 : Use CS=0 if the I/O1 is in EXT1, OR
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT2=y CONFIG_NSH_MMCSDSPIPORTNO=2 : Use CS=2 if the I/O1 is in EXT2
Application Configuration -> NSH Library Board Selection -> SAM4L Xplained Pro Modules
CONFIG_NSH_ARCHINIT=y : Board has architecture-specific initialization CONFIG_SAM4L_XPLAINED_IOMODULE=y : I/O1 module is connected
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT1=y : In EXT1, or EXT2
CONFIG_SAM4L_XPLAINED_IOMODULE_EXT2=y
NOTE: If you enable the I/O1 this configuration with USART0 as the Application Configuration -> NSH Library
console and with the I/O1 module in EXT1, you *must* remove UART CONFIG_NSH_ARCHINIT=y : Board has architecture-specific initialization
jumper. Otherwise, you have lookpack on USART0 and NSH will *not*
behave very well (since its outgoing prompts also appear as incoming
commands).
NOTE: If you get a compilation error like: NOTE: If you enable the I/O1 this configuration with USART0 as the
console and with the I/O1 module in EXT1, you *must* remove UART
jumper. Otherwise, you have lookpack on USART0 and NSH will *not*
behave very well (since its outgoing prompts also appear as incoming
commands).
libxx_new.cxx:74:40: error: 'operator new' takes type 'size_t' NOTE: If you get a compilation error like:
('unsigned int') as first parameter [-fper
Sometimes NuttX and your toolchain will disagree on the underlying libxx_new.cxx:74:40: error: 'operator new' takes type 'size_t'
type of size_t; sometimes it is an 'unsigned int' and sometimes it is ('unsigned int') as first parameter [-fper
an 'unsigned long int'. If this error occurs, then you may need to
toggle the value of CONFIG_CXX_NEWLONG.
STATUS: As of 2013-6-18, this configuration appears completely Sometimes NuttX and your toolchain will disagree on the underlying
functional. Testing, however, has been very light. Example: type of size_t; sometimes it is an 'unsigned int' and sometimes it is
an 'unsigned long int'. If this error occurs, then you may need to
toggle the value of CONFIG_CXX_NEWLONG.
NuttShell (NSH) NuttX-6.28 STATUS: As of 2013-6-18, this configuration appears completely
nsh> mount -t vfat /dev/mmcsd0 /mnt/stuff functional. Testing, however, has been very light. Example:
nsh> ls /mnt/stuff
/mnt/stuff: NuttShell (NSH) NuttX-6.28
nsh> echo "This is a test" >/mnt/stuff/atest.txt nsh> mount -t vfat /dev/mmcsd0 /mnt/stuff
nsh> ls /mnt/stuff nsh> ls /mnt/stuff
/mnt/stuff: /mnt/stuff:
atest.txt nsh> echo "This is a test" >/mnt/stuff/atest.txt
nsh> cat /mnt/stuff/atest.txt nsh> ls /mnt/stuff
This is a test /mnt/stuff:
nsh> atest.txt
nsh> cat /mnt/stuff/atest.txt
This is a test
nsh>
1. If the LCD1 module is connected to the SAM4L Xplained Pro, then
support for the SLCDt can be enabled by making the following
changes to the configuration:
System Type -> AT91SAM3/4 Peripheral Support
CONFIG_SAM34_LCDCA=y
System Type -> AT91SAM3/4 Clock Configuration
CONFIG_SAM34_OSC32K=y
Board Selection -> Board-Specific Options -> SAM4L Xplained Pro Modules
CONFIG_SAM4L_XPLAINED_SLCD1MODULE=y
Library Routines -> Non-standard Library Support
CONFIG_LIB_SLCDCODEC=y
The SLCD example can be enabled to verify the SLCD:
Application Configuration -> Examples
CONFIG_EXAMPLES_SLCD=y
CONFIG_EXAMPLES_SLCD_DEVNAME="/dev/slcd"
CONFIG_EXAMPLES_SLCD_BUFSIZE=64
Application Configuration -> NSH Library
CONFIG_NSH_ARCHINIT=y

View File

@ -65,8 +65,10 @@ CSRCS += sam_nsh.c
endif endif
ifeq ($(CONFIG_SAM34_LCDCA),y) ifeq ($(CONFIG_SAM34_LCDCA),y)
ifeq ($(CONFIG_SAM4L_XPLAINED_SLCD1MODULE),y)
CSRCS += sam_slcd.c CSRCS += sam_slcd.c
endif endif
endif
ifeq ($(CONFIG_SAM4L_XPLAINED_IOMODULE),y) ifeq ($(CONFIG_SAM4L_XPLAINED_IOMODULE),y)
CSRCS += sam_mmcsd.c CSRCS += sam_mmcsd.c

View File

@ -33,6 +33,10 @@
* *
****************************************************************************/ ****************************************************************************/
/* TODO: Add support for additional pixels: B0-B2, G0-G7, and E0-E7,
* probably via ioctl calls.
*/
/**************************************************************************** /****************************************************************************
* Included Files * Included Files
****************************************************************************/ ****************************************************************************/
@ -57,11 +61,11 @@
#include "up_arch.h" #include "up_arch.h"
#include "sam_gpio.h" #include "sam_gpio.h"
#include "sam4l_periphclks.h" #include "sam4l_periphclks.h"
#include "chip/sam_lcdca.h" #include "chip/sam4l_lcdca.h"
#include "sam4l-xplained.h" #include "sam4l-xplained.h"
#ifdef CONFIG_SAM34_LCDCA #if defined(CONFIG_SAM34_LCDCA) && defined(CONFIG_SAM4L_XPLAINED_SLCD1MODULE)
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -110,13 +114,19 @@
*/ */
#define SLCD_NROWS 1 #define SLCD_NROWS 1
#define SLCD_NCHARS 6 #define SLCD_NCHARS 5
#define SLCD_MAXCONTRAST 63 #define SLCD_MAXCONTRAST 63
#define BOARD_SLCD_NCOM 4 #define BOARD_SLCD_NCOM 4
#define BOARD_SLCD_NSEG 40 #define BOARD_SLCD_NSEG 40
#define SLCD_NPINS (BOARD_SLCD_NCOM+BOARD_SLCD_NSEG+1) #define SLCD_NPINS (BOARD_SLCD_NCOM+BOARD_SLCD_NSEG+1)
/* An ASCII character may need to be decorated with a preceding decimal
* point
*/
#define SLCD_DP 0x01
/* LCD controller bias configuration. */ /* LCD controller bias configuration. */
#undef BOARD_XBIAS #undef BOARD_XBIAS
@ -139,7 +149,7 @@
#if BOARD_SLCD_NCOM < 2 #if BOARD_SLCD_NCOM < 2
# define LCD_DUTY LCDCA_CFG_DUTY_STATIC /* Static COM0 */ # define LCD_DUTY LCDCA_CFG_DUTY_STATIC /* Static COM0 */
#elif BOARD_SLCD_NCOM < 3 #elif BOARD_SLCD_NCOM < 3
# define LCD_DUTY LCDCA_CFG_DUTY_1TO2 /* 1/2 COM[0:1] */ # define LCD_DUTY LCDCA_CFG_DUTY_1TO2 /* 1/2 COM[0:1] */
#elif BOARD_SLCD_NCOM < 4 #elif BOARD_SLCD_NCOM < 4
# define LCD_DUTY LCDCA_CFG_DUTY_1TO3 /* 1/3 COM[0:2] */ # define LCD_DUTY LCDCA_CFG_DUTY_1TO3 /* 1/3 COM[0:2] */
#elif BOARD_SLCD_NCOM < 5 #elif BOARD_SLCD_NCOM < 5
@ -148,6 +158,64 @@
# error Value of BOARD_SLCD_NCOM not supported # error Value of BOARD_SLCD_NCOM not supported
#endif #endif
/* LCD Mapping
*
* a
* ---------
* |\ |h /|
* f| g | i |b
* | \ | / |
* --j-- --k-+
* | /| \ |
* e| l | n |c
* _ | / |m \| _
* B | | --------- | | B
* - d -
*
* ----- ---- ---- ---- ----- ----------------------------------------------
* COM0 COM1 COM2 COM3 Comments
* ----- ---- ---- ---- ----- ----------------------------------------------
* SEG0 G1 G2 G4 G3 Atmel logo, 4 stage battery-, Dot-point-,
* SEG1 G0 G6 G7 G5 usband play indicator
* SEG2 E7 E5 E3 E1 4 stage wireless-, AM-, PM- Volt- and milli
* SEG3 E6 E4 E2 E0 voltindicator
* SEG4 A0-h A0-i A0-k A0-n 1st 14-segment character
* SEG5 B3 A0-f A0-e A0-d
* SEG6 A0-a A0-b A0-c B4
* SEG7 A0-g A0-j A0-l A0-m
* SEG8 A1-h A1-i A1-k A1-n 2nd 14-segment character
* SEG9 B2 A1-f A1-e A1-d
* SEG10 A1-a A1-b A1-c B5
* SEG11 A1-g A1-j A1-l A1-m
* SEG12 A2-h A2-i A2-k A2-n 3rd 14-segment character
* SEG13 B1 A2-f A2-e A2-d
* SEG14 A2-a A2-b A2-c B6
* SEG15 A2-g A2-j A2-l A2-m
* SEG16 A3-h A3-i A3-k A3-n 4th 14-segment character
* SEG17 B0 A3-f A3-e A3-d
* SEG18 A3-a A3-b A3-c B7
* SEG19 A3-g A3-j A3-l A3-m
* SEG20 A4-h A4-i A4-k A4-n 5th 14-segment character. Celsius and
* SEG21 B8 A4-f A4-e A4-d Fahrenheit indicator
* SEG22 A4-a A4-b A4-c B9
* SEG23 A4-g A4-j A4-l A4-m
*/
#define SLCD_A0_STARTSEG 4
#define SLCD_A0_ENDSEG 7
#define SLCD_A1_STARTSEG 8
#define SLCD_A1_ENDSEG 11
#define SLCD_A2_STARTSEG 12
#define SLCD_A2_ENDSEG 15
#define SLCD_A3_STARTSEG 16
#define SLCD_A3_ENDSEG 19
#define SLCD_A4_STARTSEG 20
#define SLCD_A4_ENDSEG 23
#define SLCD_NB 10 /* Number of 'B' segments B0-B9 */
#define SLCD_NG 8 /* Number of 'G' segments G0-G7 */
#define SLCD_NE 8 /* Number of 'E' segments G0-G7 */
/* Debug ********************************************************************/ /* Debug ********************************************************************/
#ifdef CONFIG_DEBUG_LCD #ifdef CONFIG_DEBUG_LCD
@ -178,6 +246,15 @@ struct sam_slcdstate_s
bool initialized; /* True: Completed initialization sequence */ bool initialized; /* True: Completed initialization sequence */
uint8_t curpos; /* The current cursor position */ uint8_t curpos; /* The current cursor position */
uint8_t buffer[SLCD_NCHARS]; /* SLCD ASCII content */ uint8_t buffer[SLCD_NCHARS]; /* SLCD ASCII content */
uint8_t options[SLCD_NCHARS]; /* Ornamentations */
};
/* Describes one pixel */
struct slcd_pixel_s
{
uint8_t segment;
uint8_t com;
}; };
/**************************************************************************** /****************************************************************************
@ -195,12 +272,21 @@ static void slcd_dumpslcd(FAR const char *msg);
/* Internal utilities */ /* Internal utilities */
#if 0 /* Not used */
static void slcd_clear(void); static void slcd_clear(void);
#endif
static void slcd_setpixel(FAR const struct slcd_pixel_s *info);
#if 0 /* Not used */
static void slcd_clrpixel(FAR const struct slcd_pixel_s *info);
#endif
static void slcd_setdp(uint8_t curpos);
#if 0 /* Not used */
static void slcd_clrdp(uint8_t curpos);
#endif
static int slcd_getstream(FAR struct lib_instream_s *instream); static int slcd_getstream(FAR struct lib_instream_s *instream);
static uint8_t slcd_getcontrast(void); static uint8_t slcd_getcontrast(void);
static int slcd_setcontrast(int contrast); static int slcd_setcontrast(unsigned int contrast);
static void slcd_writech(uint8_t ch, uint8_t curpos); static void slcd_writech(uint8_t ch, uint8_t curpos);
static void slcd_appendch(uint8_t ch);
static void slcd_action(enum slcdcode_e code, uint8_t count); static void slcd_action(enum slcdcode_e code, uint8_t count);
/* Character driver methods */ /* Character driver methods */
@ -253,6 +339,38 @@ static gpio_pinset_t g_slcdgpio[SLCD_NPINS] =
GPIO_LCD1_BL GPIO_LCD1_BL
}; };
/* First segment of each character */
static const uint8_t g_startseg[SLCD_NCHARS] =
{
SLCD_A0_STARTSEG, SLCD_A1_STARTSEG, SLCD_A2_STARTSEG, SLCD_A3_STARTSEG,
SLCD_A4_STARTSEG
};
/* Pixel position for each 'B' segment */
static const struct slcd_pixel_s g_binfo[SLCD_NB] =
{
{17, 0}, {13, 0}, {9, 0}, {5, 0}, {6, 3},
{10, 3}, {14, 3}, {18, 3}, {21, 0}, {22, 3}
};
/* Pixel position for each 'G' segment */
static const struct slcd_pixel_s g_ginfo[SLCD_NG] =
{
{1, 0}, {0, 0}, {0, 1}, {0, 3}, {0, 2},
{1, 3}, {1, 1}, {1, 2}
};
/* Pixel position for each 'E' segment */
static const struct slcd_pixel_s g_einfo[SLCD_NE] =
{
{3, 3}, {2, 3}, {3, 2}, {2, 2}, {3, 1},
{2, 1}, {3, 0}, {2, 0}
};
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -267,9 +385,12 @@ static void slcd_dumpstate(FAR const char *msg)
lcdvdbg("%s:\n", msg); lcdvdbg("%s:\n", msg);
lcdvdbg(" curpos: %d\n", lcdvdbg(" curpos: %d\n",
g_slcdstate.curpos); g_slcdstate.curpos);
lcdvdbg(" Display: [%c%c%c%c%c%c]\n", lcdvdbg(" Display: [%c%c%c%c%c]\n",
g_slcdstate.buffer[0], g_slcdstate.buffer[1], g_slcdstate.buffer[2], g_slcdstate.buffer[0], g_slcdstate.buffer[1], g_slcdstate.buffer[2],
g_slcdstate.buffer[3], g_slcdstate.buffer[4], g_slcdstate.buffer[5]); g_slcdstate.buffer[3], g_slcdstate.buffer[4]);
lcdvdbg(" Options: [%d%d%d%d%d]\n",
g_slcdstate.options[0], g_slcdstate.options[1], g_slcdstate.options[2],
g_slcdstate.options[3], g_slcdstate.options[4]);
} }
#endif #endif
@ -303,13 +424,82 @@ static void slcd_dumpslcd(FAR const char *msg)
* Name: slcd_clear * Name: slcd_clear
****************************************************************************/ ****************************************************************************/
#if 0 /* Not used */
static void slcd_clear(void) static void slcd_clear(void)
{ {
uint32_t regaddr;
lvdbg("Clearing\n"); lvdbg("Clearing\n");
#warning Missing logic
/* Clear display memory */
putreg32(LCDCA_CR_CDM, SAM_LCDCA_CR);
} }
#endif
/****************************************************************************
* Name: slcd_setpixel
****************************************************************************/
static void slcd_setpixel(FAR const struct slcd_pixel_s *info)
{
uintptr_t regaddr;
uint32_t regval;
regaddr = info->com ? SAM_LCDCA_DRL0 : SAM_LCDCA_DRL3;
regval = getreg32(regaddr);
regval |= (1 << info->segment);
putreg32(regval, regaddr);
}
/****************************************************************************
* Name: slcd_clrpixel
****************************************************************************/
#if 0 /* Not used */
static void slcd_clrpixel(FAR const struct slcd_pixel_s *info)
{
uintptr_t regaddr;
uint32_t regval;
regaddr = info->com ? SAM_LCDCA_DRL0 : SAM_LCDCA_DRL3;
regval = getreg32(regaddr);
regval &= ~(1 << info->segment);
putreg32(regval, regaddr);
}
#endif
/****************************************************************************
* Name: slcd_setdp
****************************************************************************/
static void slcd_setdp(uint8_t curpos)
{
/* Set the decimal point before the current cursor position
*
* B3 B4 B5 B6 B7
* .O .O .O .O .O
*/
slcd_setpixel(&g_binfo[curpos + 3]);
g_slcdstate.options[curpos] |= SLCD_DP;
}
/****************************************************************************
* Name: slcd_clrdp
****************************************************************************/
#if 0 /* Not used */
static void slcd_clrdp(uint8_t curpos)
{
/* Set the decimal point before the current cursor position
*
* B3 B4 B5 B6 B7
* .O .O .O .O .O
*/
slcd_clrpixel(&g_binfo[curpos + 3]);
g_slcdstate.options[curpos] &= ~SLCD_DP;
}
#endif
/**************************************************************************** /****************************************************************************
* Name: slcd_getstream * Name: slcd_getstream
@ -347,7 +537,7 @@ static uint8_t slcd_getcontrast(void)
/* Get the current contast value */ /* Get the current contast value */
regval = getreg32(SAM_LCDCA_CFG); regval = getreg32(SAM_LCDCA_CFG);
ucontrast = (regval & LCDCA_CFG_FCST_MASK) >> LCDCA_CFG_FCST_MASK; ucontrast = (regval & LCDCA_CFG_FCST_MASK) >> LCDCA_CFG_FCST_SHIFT;
/* Sign extend and translate the 6 bit signed value /* Sign extend and translate the 6 bit signed value
* *
@ -411,13 +601,26 @@ static int slcd_setcontrast(unsigned int contrast)
static void slcd_writech(uint8_t ch, uint8_t curpos) static void slcd_writech(uint8_t ch, uint8_t curpos)
{ {
uint16_t segset; uint8_t segment;
/* Get a set describing the segment settings */ /* "LCDCA handles up to four ASCII characters tables, configured in
* Character Mapping Configuration register (CMCFG). Instead of handling
* each segments in display memory for a selected digit, user writes ASCII
* code in Character Mapping Control Register (CMCR) to display the
* corresponding character.
*
* "User can then drive several digits with few operations:
*
* "1. Select the Type of Digit (CMCFG.TDG),
* "2. Write the Start Segment value (CMCFG.STSEG) of the first digit,
* "3. Select Digit Reverse Mode (CMCFG.DREV) if required. If DREV is one,
* segment index is decremented,
* "4. Then write ASCII code in CMCR register."
*/
#warning Missing logic segment = g_startseg[curpos];
putreg32(LCDCA_CMCFG_TDG_14S4C | LCDCA_CMCFG_STSEG(segment), SAM_LCDCA_CMCFG);
/* Decode the value and write it to the SLCD segment memory */ putreg32(ch, SAM_LCDCA_CMDR);
/* Save these values in the state structure */ /* Save these values in the state structure */
@ -425,25 +628,6 @@ static void slcd_writech(uint8_t ch, uint8_t curpos)
slcd_dumpstate("AFTER WRITE"); slcd_dumpstate("AFTER WRITE");
} }
/****************************************************************************
* Name: slcd_appendch
****************************************************************************/
static void slcd_appendch(uint8_t ch, uint8)
{
lcdvdbg("ch: %c[%02x]\n", isprint(ch) ? ch : '.', ch);
/* Write the character at the current cursor position */
slcd_writech(ch, g_slcdstate.curpos);
if (g_slcdstate.curpos < (SLCD_NCHARS - 1))
{
g_slcdstate.curpos++;
}
slcd_dumpstate("AFTER APPEND");
}
/**************************************************************************** /****************************************************************************
* Name: slcd_action * Name: slcd_action
****************************************************************************/ ****************************************************************************/
@ -510,7 +694,7 @@ static void slcd_action(enum slcdcode_e code, uint8_t count)
for (i = SLCD_NCHARS - nmove; i < SLCD_NCHARS; i++) for (i = SLCD_NCHARS - nmove; i < SLCD_NCHARS; i++)
{ {
slcd_writech(' ', i, 0); slcd_writech(' ', i);
} }
} }
break; break;
@ -535,7 +719,7 @@ static void slcd_action(enum slcdcode_e code, uint8_t count)
for (i = g_slcdstate.curpos; i < last; i++) for (i = g_slcdstate.curpos; i < last; i++)
{ {
slcd_writech(' ', i, 0); slcd_writech(' ', i);
} }
} }
break; break;
@ -557,7 +741,7 @@ static void slcd_action(enum slcdcode_e code, uint8_t count)
for (i = g_slcdstate.curpos; i < SLCD_NCHARS; i++) for (i = g_slcdstate.curpos; i < SLCD_NCHARS; i++)
{ {
slcd_writech(' ', i, 0); slcd_writech(' ', i);
} }
} }
break; break;
@ -649,26 +833,20 @@ static ssize_t slcd_read(FAR struct file *filp, FAR char *buffer, size_t len)
for (i = 0; i < SLCD_NCHARS && ret < len; i++) for (i = 0; i < SLCD_NCHARS && ret < len; i++)
{ {
/* Return the character */ /* Check if the character is decorated with a preceding period */
*buffer++ = g_slcdstate.buffer[i]; if (ret < len && g_slcdstate.options[i] != 0)
ret++;
/* Check if the character is decorated with a folling period or colon */
if (ret < len && g_slcdstate.buffer[i] != 0)
{ {
if ((g_slcdstate.buffer[i] & SLCD_DP) != 0) if ((g_slcdstate.options[i] & SLCD_DP) != 0)
{ {
*buffer++ = '.'; *buffer++ = '.';
ret++; ret++;
} }
else if ((g_slcdstate.buffer[i] & SLCD_COLON) != 0)
{
*buffer++ = ':';
ret++;
}
} }
/* Return the character */
*buffer++ = g_slcdstate.buffer[i];
ret++;
} }
slcd_dumpstate("READ"); slcd_dumpstate("READ");
@ -685,10 +863,9 @@ static ssize_t slcd_write(FAR struct file *filp,
struct slcd_instream_s instream; struct slcd_instream_s instream;
struct slcdstate_s state; struct slcdstate_s state;
enum slcdret_e result; enum slcdret_e result;
bool dotneeded;
uint8_t ch; uint8_t ch;
uint8_t count; uint8_t count;
uint8_t prev = ' ';
bool valid = false;
/* Initialize the stream for use with the SLCD CODEC */ /* Initialize the stream for use with the SLCD CODEC */
@ -697,35 +874,9 @@ static ssize_t slcd_write(FAR struct file *filp,
instream.buffer = buffer; instream.buffer = buffer;
instream.nbytes = len; instream.nbytes = len;
/* Prime the pump. This is messy, but necessary to handle decoration on a /* Decode and process every byte in the input buffer */
* character based on any following period or colon.
*/
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:
{
slcd_action((enum slcdcode_e)prev, count);
prev = ' ';
}
break;
case SLCDRET_EOF:
return 0;
}
/* Now decode and process every byte in the input buffer */
dotneeded = false;
while ((result = slcd_decode(&instream.stream, &state, &ch, &count)) != SLCDRET_EOF) while ((result = slcd_decode(&instream.stream, &state, &ch, &count)) != SLCDRET_EOF)
{ {
lcdvdbg("slcd_decode returned result=%d char=%d count=%d\n", lcdvdbg("slcd_decode returned result=%d char=%d count=%d\n",
@ -741,121 +892,79 @@ static ssize_t slcd_write(FAR struct file *filp,
if (ch == ASCII_BS) if (ch == ASCII_BS)
{ {
/* If there is a pending character, then output it now before /* Perform the backward deletion */
* performing the action.
*/
if (valid)
{
slcd_appendch(prev, 0);
prev = ' ';
valid = false;
}
/* Then perform the backward deletion */
slcd_action(SLCDCODE_BACKDEL, 1); slcd_action(SLCDCODE_BACKDEL, 1);
} }
else if (ch == ASCII_CR) else if (ch == ASCII_CR)
{ {
/* If there is a pending character, then output it now before /* Perform the carriage return */
* performing the action.
*/
if (valid)
{
slcd_appendch(prev, 0);
prev = ' ';
valid = false;
}
/* Then perform the carriage return */
slcd_action(SLCDCODE_HOME, 0); slcd_action(SLCDCODE_HOME, 0);
} }
/* Ignore dots before control characters (all of them?) */
dotneeded = false;
} }
/* Handle characters decoreated with a period or a colon */ /* Handle characters decoreated with a preceding period */
else if (ch == '.') else if (ch == '.')
{ {
/* Write the previous character with the decimal point appended */ /* The next character will need a dot in front of it */
slcd_appendch(prev, SLCD_DP); dotneeded = true;
prev = ' ';
valid = false;
}
else if (ch == ':')
{
/* Write the previous character with the colon appended */
slcd_appendch(prev, SLCD_COLON);
prev = ' ';
valid = false;
} }
/* Handle ASCII_DEL */ /* Handle ASCII_DEL */
else if (ch == ASCII_DEL) else if (ch == ASCII_DEL)
{ {
/* If there is a pending character, then output it now before /* Perform the foward deletion */
* performing the action.
*/
if (valid)
{
slcd_appendch(prev, 0);
prev = ' ';
valid = false;
}
/* Then perform the foward deletion */
slcd_action(SLCDCODE_FWDDEL, 1); slcd_action(SLCDCODE_FWDDEL, 1);
dotneeded = false;
} }
/* The rest of the 7-bit ASCII characters are fair game */ /* The rest of the 7-bit ASCII characters are fair game */
else if (ch < 128) else if (ch < 128)
{ {
/* Write the previous character if it valid */ lcdvdbg("ch: %c[%02x]\n", ch, ch);
if (valid) /* Write the character at the current cursor position */
slcd_writech(ch, g_slcdstate.curpos);
/* Check if we need to decorate the character with a preceding
* dot.
*/
if (dotneeded)
{ {
slcd_appendch(prev, 0); slcd_setdp(g_slcdstate.curpos);
} }
/* There is now a valid output character */ /* And advance the cursor position */
prev = ch; if (g_slcdstate.curpos < (SLCD_NCHARS - 1))
valid = true; {
g_slcdstate.curpos++;
}
slcd_dumpstate("AFTER APPEND");
} }
} }
else /* (result == SLCDRET_SPEC) */ /* A special SLCD action was returned */ else /* (result == SLCDRET_SPEC) */ /* A special SLCD action was returned */
{ {
/* If there is a pending character, then output it now before /* Then Perform the action */
* performing the action.
*/
if (valid)
{
slcd_appendch(prev, 0);
prev = ' ';
valid = false;
}
/* Then perform the action */
slcd_action((enum slcdcode_e)ch, count); slcd_action((enum slcdcode_e)ch, count);
} }
} }
/* Handle any unfinished output */ /* Ignore any dots with no following characters */
if (valid)
{
slcd_appendch(prev, 0);
}
/* Assume that the entire input buffer was processed */ /* Assume that the entire input buffer was processed */
@ -952,7 +1061,7 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg)
return -ERANGE; return -ERANGE;
} }
return slcd_setcontrast((int)arg); return slcd_setcontrast((unsigned int)arg);
} }
break; break;
@ -1063,7 +1172,7 @@ int sam_slcd_initialize(void)
#endif #endif
LCD_DUTY | LCD_DUTY |
LCDCA_CFG_FCST(0) | LCDCA_CFG_FCST(0) |
LCDCA_CFG_NSU(BOARD_SLCD_NSEG)); LCDCA_CFG_NSU(BOARD_SLCD_NSEG);
putreg32(regval, SAM_LCDCA_CFG); putreg32(regval, SAM_LCDCA_CFG);
@ -1102,8 +1211,7 @@ int sam_slcd_initialize(void)
/* Make sure that blinking and circular shifting is off */ /* Make sure that blinking and circular shifting is off */
putreg32(LCDCA_CR_BSTOP | , SAM_LCDCA_CR); putreg32(LCDCA_CR_BSTOP | LCDCA_CR_CSTOP, SAM_LCDCA_CR);
putreg32(LCDCA_CR_CSTOP, SAM_LCDCA_CR);
/* Disable any automated display */ /* Disable any automated display */
@ -1136,4 +1244,4 @@ int sam_slcd_initialize(void)
return ret; return ret;
} }
#endif /* CONFIG_SAM34_LCDCA */ #endif /* CONFIG_SAM34_LCDCA && CONFIG_SAM4L_XPLAINED_SLCD1MODULE */

View File

@ -366,7 +366,7 @@ static struct stm32_slcdstate_s g_slcdstate;
* D * D
* *
* LCD character 16-bit-encoding: * LCD character 16-bit-encoding:
* { E , D , P , N, M , C , COL , DP, B , A , K , J, G , F , Q , H } * { E , D , P , N, M , C , COL , DP, B , A , K , J, G , F , Q , H }
*/ */
#warning "Encodings for all punctuation are incomplete" #warning "Encodings for all punctuation are incomplete"
@ -701,7 +701,7 @@ static inline void slcd_writemem(uint16_t segset, int curpos)
/* Isolate the least significant bits /* Isolate the least significant bits
* *
* LCD character 16-bit-encoding: * LCD character 16-bit-encoding:
* { E , D , P , N, M , C , COL , DP, B , A , K , J, G , F , Q , H } * { E , D , P , N, M , C , COL , DP, B , A , K , J, G , F , Q , H }
* *
* segments[0] = { E , D , P , N } * segments[0] = { E , D , P , N }
* segments[1] = { M , C , COL , DP } * segments[1] = { M , C , COL , DP }