From c82f81e5736e0c833e2c62603542e1cbbd83fed7 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 23 Jun 2013 09:05:20 -0600 Subject: SAM4L Xplained SLCD driver is complete --- nuttx/ChangeLog | 2 + nuttx/arch/arm/src/sam34/chip/sam4l_lcdca.h | 8 ++ nuttx/configs/sam4l-xplained/README.txt | 5 +- nuttx/configs/sam4l-xplained/src/sam_slcd.c | 194 ++++++++++++++++++-------- nuttx/configs/stm32ldiscovery/src/stm32_lcd.c | 1 - 5 files changed, 152 insertions(+), 58 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 9693f75aa..03ba24550 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5030,3 +5030,5 @@ in (2013-6-21). * drivers/net/enc28j60.c: Change buffer ordering to work around Errata #5. From Dave (ziggurat29, 2013-6-22). + * configs/sam4l-xplained/src/sam_slcd.c: LED1 segment LCD module is now + functional (2013-6-23). diff --git a/nuttx/arch/arm/src/sam34/chip/sam4l_lcdca.h b/nuttx/arch/arm/src/sam34/chip/sam4l_lcdca.h index 7e17ba347..7d179cb02 100644 --- a/nuttx/arch/arm/src/sam34/chip/sam4l_lcdca.h +++ b/nuttx/arch/arm/src/sam34/chip/sam4l_lcdca.h @@ -56,6 +56,9 @@ #define SAM_LCDCA_TIM_OFFSET 0x0008 /* Timing Register */ #define SAM_LCDCA_SR_OFFSET 0x000c /* Status Register */ #define SAM_LCDCA_SCR_OFFSET 0x0010 /* Status Clear Register */ + +#define SAM_LCDCA_DRL_OFFSET(n) (0x0014+((n)<<3)) +#define SAM_LCDCA_DRH_OFFSET(n) (0x0018+((n)<<3)) #define SAM_LCDCA_DRL0_OFFSET 0x0014 /* Data Register Low 0 */ #define SAM_LCDCA_DRH0_OFFSET 0x0018 /* Data Register High 0 */ #define SAM_LCDCA_DRL1_OFFSET 0x001c /* Data Register Low 1 */ @@ -64,6 +67,7 @@ #define SAM_LCDCA_DRH2_OFFSET 0x0028 /* Data Register High 2 */ #define SAM_LCDCA_DRL3_OFFSET 0x002c /* Data Register Low 3 */ #define SAM_LCDCA_DRH3_OFFSET 0x0030 /* Data Register High 3 */ + #define SAM_LCDCA_IADR_OFFSET 0x0034 /* Indirect Access Data Register */ #define SAM_LCDCA_BCFG_OFFSET 0x0038 /* Blink Configuration Register */ #define SAM_LCDCA_CSRCFG_OFFSET 0x003c /* Circular Shift Register Configuration */ @@ -85,6 +89,9 @@ #define SAM_LCDCA_TIM (SAM_LCDCA_BASE+SAM_LCDCA_TIM_OFFSET) #define SAM_LCDCA_SR (SAM_LCDCA_BASE+SAM_LCDCA_SR_OFFSET) #define SAM_LCDCA_SCR (SAM_LCDCA_BASE+SAM_LCDCA_SCR_OFFSET) + +#define SAM_LCDCA_DRL(n) (SAM_LCDCA_BASE+SAM_LCDCA_DRL_OFFSET(n)) +#define SAM_LCDCA_DRH(n) (SAM_LCDCA_BASE+SAM_LCDCA_DRH_OFFSET(n)) #define SAM_LCDCA_DRL0 (SAM_LCDCA_BASE+SAM_LCDCA_DRL0_OFFSET) #define SAM_LCDCA_DRH0 (SAM_LCDCA_BASE+SAM_LCDCA_DRH0_OFFSET) #define SAM_LCDCA_DRL1 (SAM_LCDCA_BASE+SAM_LCDCA_DRL1_OFFSET) @@ -93,6 +100,7 @@ #define SAM_LCDCA_DRH2 (SAM_LCDCA_BASE+SAM_LCDCA_DRH2_OFFSET) #define SAM_LCDCA_DRL3 (SAM_LCDCA_BASE+SAM_LCDCA_DRL3_OFFSET) #define SAM_LCDCA_DRH3 (SAM_LCDCA_BASE+SAM_LCDCA_DRH3_OFFSET) + #define SAM_LCDCA_IADR (SAM_LCDCA_BASE+SAM_LCDCA_IADR_OFFSET) #define SAM_LCDCA_BCFG (SAM_LCDCA_BASE+SAM_LCDCA_BCFG_OFFSET) #define SAM_LCDCA_CSRCFG (SAM_LCDCA_BASE+SAM_LCDCA_CSRCFG_OFFSET) diff --git a/nuttx/configs/sam4l-xplained/README.txt b/nuttx/configs/sam4l-xplained/README.txt index dfdd362a1..17971ba4d 100644 --- a/nuttx/configs/sam4l-xplained/README.txt +++ b/nuttx/configs/sam4l-xplained/README.txt @@ -755,7 +755,7 @@ Configuration sub-directories This is a test nsh> - 1. If the LCD1 module is connected to the SAM4L Xplained Pro, then + 2. 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: @@ -784,3 +784,6 @@ Configuration sub-directories Application Configuration -> NSH Library CONFIG_NSH_ARCHINIT=y + + NOTE: In order to use the segment LCD you *must* open the VLCD_A and + VLCD_BC jumpers or the SLD will not be powered! diff --git a/nuttx/configs/sam4l-xplained/src/sam_slcd.c b/nuttx/configs/sam4l-xplained/src/sam_slcd.c index f0acba70a..898c7e883 100644 --- a/nuttx/configs/sam4l-xplained/src/sam_slcd.c +++ b/nuttx/configs/sam4l-xplained/src/sam_slcd.c @@ -115,6 +115,7 @@ #define SLCD_NROWS 1 #define SLCD_NCHARS 5 +#define SLCD_NBARS 4 #define SLCD_MAXCONTRAST 63 #define BOARD_SLCD_NCOM 4 @@ -216,6 +217,37 @@ #define SLCD_NG 8 /* Number of 'G' segments G0-G7 */ #define SLCD_NE 8 /* Number of 'E' segments G0-G7 */ +/* Named pixels */ + +#define SLCD_MINUS (&g_binfo[0]) +#define SLCD_H (&g_binfo[1]) +#define SLCD_M (&g_binfo[2]) +#define SLCD_DP0 (&g_binfo[3]) +#define SLCD_DP1 (&g_binfo[4]) +#define SLCD_DP2 (&g_binfo[5]) +#define SLCD_DP3 (&g_binfo[6]) +#define SLCD_DP4 (&g_binfo[7]) +#define SLCD_CENTIGRADE (&g_binfo[8]) +#define SLCD_FAHRENHEIT (&g_binfo[9]) + +#define SLCD_ATMEL (&g_ginfo[0]) +#define SLCD_BAR0 (&g_ginfo[1]) +#define SLCD_BAR1 (&g_ginfo[2]) +#define SLCD_BAR2 (&g_ginfo[3]) +#define SLCD_BAR3 (&g_ginfo[4]) +#define SLCD_COLON (&g_ginfo[5]) +#define SLCD_USB (&g_ginfo[6]) +#define SLCD_PAY (&g_ginfo[7]) + +#define SLCD_RNG0 (&g_einfo[0]) +#define SLCD_RNG1 (&g_einfo[1]) +#define SLCD_RNG2 (&g_einfo[2]) +#define SLCD_RNG3 (&g_einfo[3]) +#define SLCD_MV (&g_einfo[4]) +#define SLCD_V (&g_einfo[5]) +#define SLCD_PM (&g_einfo[6]) +#define SLCD_AM (&g_einfo[7]) + /* Debug ********************************************************************/ #ifdef CONFIG_DEBUG_LCD @@ -276,17 +308,13 @@ static void slcd_dumpslcd(FAR const char *msg); 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 inline void slcd_setdp(uint8_t curpos); +static inline void slcd_clrdp(uint8_t curpos); static int slcd_getstream(FAR struct lib_instream_s *instream); static uint8_t slcd_getcontrast(void); 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, uint8_t options); static void slcd_action(enum slcdcode_e code, uint8_t count); /* Character driver methods */ @@ -403,12 +431,12 @@ static void slcd_dumpslcd(FAR const char *msg) lcdvdbg(" CFG: %08x TIM: %08x SR: %08x\n", getreg32(SAM_LCDCA_CFG), getreg32(SAM_LCDCA_TIM), getreg32(SAM_LCDCA_SR)); - lcdvdbg(" DR0: %08x %08x DR1: %08x %08x\n", - getreg32(SAM_LCDCA_DRL0), getreg32(SAM_LCDCA_DRH0), - getreg32(SAM_LCDCA_DRL1), getreg32(SAM_LCDCA_DRH1)); - lcdvdbg(" DR2: %08x %08x DR3: %08x %08x\n", - getreg32(SAM_LCDCA_DRL2), getreg32(SAM_LCDCA_DRH2), - getreg32(SAM_LCDCA_DRL3), getreg32(SAM_LCDCA_DRH3)); + lcdvdbg(" DR0: %02x %08x DR1: %02x %08x\n", + getreg32(SAM_LCDCA_DRH0), getreg32(SAM_LCDCA_DRL0), + getreg32(SAM_LCDCA_DRH1), getreg32(SAM_LCDCA_DRL1)); + lcdvdbg(" DR2: %02x %08x DR3: %02x %08x\n", + getreg32(SAM_LCDCA_DRH2), getreg32(SAM_LCDCA_DRL2), + getreg32(SAM_LCDCA_DRH3), getreg32(SAM_LCDCA_DRL3)); lcdvdbg(" BCFG: %08x CSRCFG: %08x CMCFG: %08x ACMCFG: %08x\n", getreg32(SAM_LCDCA_BCFG), getreg32(SAM_LCDCA_CSRCFG), getreg32(SAM_LCDCA_CMCFG), getreg32(SAM_LCDCA_ACMCFG)); @@ -442,7 +470,7 @@ 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; + regaddr = SAM_LCDCA_DRL(info->com); regval = getreg32(regaddr); regval |= (1 << info->segment); putreg32(regval, regaddr); @@ -452,24 +480,22 @@ static void slcd_setpixel(FAR const struct slcd_pixel_s *info) * 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; + regaddr = SAM_LCDCA_DRL(info->com); regval = getreg32(regaddr); regval &= ~(1 << info->segment); putreg32(regval, regaddr); } -#endif /**************************************************************************** * Name: slcd_setdp ****************************************************************************/ -static void slcd_setdp(uint8_t curpos) +static inline void slcd_setdp(uint8_t curpos) { /* Set the decimal point before the current cursor position * @@ -478,15 +504,13 @@ static void slcd_setdp(uint8_t curpos) */ 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) +static inline void slcd_clrdp(uint8_t curpos) { /* Set the decimal point before the current cursor position * @@ -495,9 +519,7 @@ static void slcd_clrdp(uint8_t curpos) */ slcd_clrpixel(&g_binfo[curpos + 3]); - g_slcdstate.options[curpos] &= ~SLCD_DP; } -#endif /**************************************************************************** * Name: slcd_getstream @@ -597,7 +619,7 @@ static int slcd_setcontrast(unsigned int contrast) * Name: slcd_writech ****************************************************************************/ -static void slcd_writech(uint8_t ch, uint8_t curpos) +static void slcd_writech(uint8_t ch, uint8_t curpos, uint8_t options) { uint8_t segment; @@ -620,9 +642,21 @@ static void slcd_writech(uint8_t ch, uint8_t curpos) putreg32(LCDCA_CMCFG_TDG_14S4C | LCDCA_CMCFG_STSEG(segment), SAM_LCDCA_CMCFG); putreg32(ch, SAM_LCDCA_CMDR); + /* Check if we need to decorate the character with a preceding dot. */ + + if ((options & SLCD_DP) != 0) + { + slcd_setdp(curpos); + } + else + { + slcd_clrdp(curpos); + } + /* Save these values in the state structure */ g_slcdstate.buffer[curpos] = ch; + g_slcdstate.options[curpos] = options; slcd_dumpstate("AFTER WRITE"); } @@ -681,18 +715,21 @@ static void slcd_action(enum slcdcode_e code, uint8_t count) nchars = SLCD_NCHARS - g_slcdstate.curpos; nmove = MIN(nchars, count) - 1; - /* Move all characters after the current cursor position left by 'nmove' characters */ + /* 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); + 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); + slcd_writech(' ', i, 0); } } break; @@ -717,7 +754,7 @@ static void slcd_action(enum slcdcode_e code, uint8_t count) for (i = g_slcdstate.curpos; i < last; i++) { - slcd_writech(' ', i); + slcd_writech(' ', i, 0); } } break; @@ -739,7 +776,7 @@ static void slcd_action(enum slcdcode_e code, uint8_t count) for (i = g_slcdstate.curpos; i < SLCD_NCHARS; i++) { - slcd_writech(' ', i); + slcd_writech(' ', i, 0); } } break; @@ -861,9 +898,9 @@ static ssize_t slcd_write(FAR struct file *filp, struct slcd_instream_s instream; struct slcdstate_s state; enum slcdret_e result; - bool dotneeded; uint8_t ch; uint8_t count; + uint8_t options; /* Initialize the stream for use with the SLCD CODEC */ @@ -872,9 +909,13 @@ static ssize_t slcd_write(FAR struct file *filp, instream.buffer = buffer; instream.nbytes = len; + /* Initialize the SLCD decode state buffer */ + + memset(&state, 0, sizeof(struct slcdstate_s)); + /* Decode and process every byte in the input buffer */ - dotneeded = false; + options = 0; while ((result = slcd_decode(&instream.stream, &state, &ch, &count)) != SLCDRET_EOF) { lcdvdbg("slcd_decode returned result=%d char=%d count=%d\n", @@ -903,7 +944,7 @@ static ssize_t slcd_write(FAR struct file *filp, /* Ignore dots before control characters (all of them?) */ - dotneeded = false; + options = 0; } /* Handle characters decoreated with a preceding period */ @@ -912,7 +953,7 @@ static ssize_t slcd_write(FAR struct file *filp, { /* The next character will need a dot in front of it */ - dotneeded = true; + options |= SLCD_DP; } /* Handle ASCII_DEL */ @@ -922,27 +963,19 @@ static ssize_t slcd_write(FAR struct file *filp, /* Perform the foward deletion */ slcd_action(SLCDCODE_FWDDEL, 1); - dotneeded = false; + options = 0; } /* The rest of the 7-bit ASCII characters are fair game */ else if (ch < 128) { - lcdvdbg("ch: %c[%02x]\n", ch, ch); + lcdvdbg("ch: %c[%02x] options: %02x\n", ch, ch, options); /* 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_setdp(g_slcdstate.curpos); - } + slcd_writech(ch, g_slcdstate.curpos, options); + options = 0; /* And advance the cursor position */ @@ -997,7 +1030,7 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg) attr->nrows = SLCD_NROWS; attr->ncolumns = SLCD_NCHARS; - attr->nbars = 0; + attr->nbars = SLCD_NBARS; attr->maxcontrast = SLCD_MAXCONTRAST; attr->maxbrightness = 0; } @@ -1009,7 +1042,6 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg) * returned */ - case SLCDIOC_CURPOS: { FAR struct slcd_curpos_s *curpos = (FAR struct slcd_curpos_s *)((uintptr_t)arg); @@ -1026,6 +1058,53 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg) } break; + /* SLCDIOC_SETBAR: Set bars on a bar display + * + * argument: 32-bit bitset, with each bit corresponding to one bar. + */ + + case SLCDIOC_SETBAR: + { + lcdvdbg("SLCDIOC_SETBAR: arg=0x%02lx\n", arg); + + if ((arg & 1) != 0) + { + slcd_setpixel(SLCD_RNG0); + } + else + { + slcd_clrpixel(SLCD_RNG0); + } + + if ((arg & 2) != 0) + { + slcd_setpixel(SLCD_RNG1); + } + else + { + slcd_clrpixel(SLCD_RNG1); + } + + if ((arg & 4) != 0) + { + slcd_setpixel(SLCD_RNG2); + } + else + { + slcd_clrpixel(SLCD_RNG2); + } + + if ((arg & 8) != 0) + { + slcd_clrpixel(SLCD_RNG3); + } + else + { + slcd_setpixel(SLCD_RNG3); + } + } + break; + /* SLCDIOC_GETCONTRAST: Get the current contrast setting * * argument: Pointer type int that will receive the current contrast @@ -1063,7 +1142,6 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg) } break; - case SLCDIOC_SETBAR: /* Get bar levels */ case SLCDIOC_GETBRIGHTNESS: /* Get the current brightness setting */ case SLCDIOC_SETBRIGHTNESS: /* Set the brightness to a new value */ default: @@ -1219,14 +1297,18 @@ int sam_slcd_initialize(void) /* Initialize display memory */ - putreg32(LCDCA_DRL_MASK, SAM_LCDCA_DRL0); - putreg32(LCDCA_DRH_MASK, SAM_LCDCA_DRH0); - putreg32(LCDCA_DRL_MASK, SAM_LCDCA_DRL1); - putreg32(LCDCA_DRH_MASK, SAM_LCDCA_DRH1); - putreg32(LCDCA_DRL_MASK, SAM_LCDCA_DRL2); - putreg32(LCDCA_DRH_MASK, SAM_LCDCA_DRH2); - putreg32(LCDCA_DRL_MASK, SAM_LCDCA_DRL3); - putreg32(LCDCA_DRH_MASK, SAM_LCDCA_DRH3); + putreg32(0, SAM_LCDCA_DRL0); + putreg32(0, SAM_LCDCA_DRH0); + putreg32(0, SAM_LCDCA_DRL1); + putreg32(0, SAM_LCDCA_DRH1); + putreg32(0, SAM_LCDCA_DRL2); + putreg32(0, SAM_LCDCA_DRH2); + putreg32(0, SAM_LCDCA_DRL3); + putreg32(0, SAM_LCDCA_DRH3); + + /* Turn on the Atmel pixel */ + + slcd_setpixel(SLCD_ATMEL); /* Register the LCD device driver */ diff --git a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c index 1dc9e25d2..c74836959 100644 --- a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c +++ b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c @@ -1350,7 +1350,6 @@ static int slcd_ioctl(FAR struct file *filp, int cmd, unsigned long arg) * returned */ - case SLCDIOC_CURPOS: { FAR struct slcd_curpos_s *curpos = (FAR struct slcd_curpos_s *)((uintptr_t)arg); -- cgit v1.2.3