diff --git a/drivers/lcd/lcd_framebuffer.c b/drivers/lcd/lcd_framebuffer.c index b97b10d25e..b3ee46bdb6 100644 --- a/drivers/lcd/lcd_framebuffer.c +++ b/drivers/lcd/lcd_framebuffer.c @@ -1,7 +1,7 @@ /**************************************************************************** * drivers/lcd/lcd_frambuffer.c * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017=-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -88,7 +88,7 @@ struct lcdfb_dev_s /* Update the LCD when there is a change to the framebuffer */ -static void lcdfb_update(FAR struct lcdfb_dev_s *priv, +static int lcdfb_update(FAR struct lcdfb_dev_s *priv, FAR const struct nxgl_rect_s *rect); /* Get information about the video controller configuration and the @@ -174,8 +174,8 @@ static FAR struct lcdfb_dev_s *lcdfb_find(int display) * ****************************************************************************/ -static void lcdfb_update(FAR struct lcdfb_dev_s *priv, - FAR const struct nxgl_rect_s *rect) +static int lcdfb_update(FAR struct lcdfb_dev_s *priv, + FAR const struct nxgl_rect_s *rect) { FAR struct lcd_planeinfo_s *pinfo = &priv->pinfo; FAR uint8_t *run; @@ -185,6 +185,7 @@ static void lcdfb_update(FAR struct lcdfb_dev_s *priv, fb_coord_t width; fb_coord_t starty; fb_coord_t endy; + int ret; /* Clip to fit in the framebuffer */ @@ -235,9 +236,16 @@ static void lcdfb_update(FAR struct lcdfb_dev_s *priv, * memory. */ - pinfo->putrun(row, startx, run, width); + ret = pinfo->putrun(row, startx, run, width); + if (ret < 0) + { + return ret; + } + run += priv->stride; } + + return OK; } /**************************************************************************** @@ -573,7 +581,11 @@ int up_fbinitialize(int display) rect.pt2.x = priv->xres - 1; rect.pt2.y = priv->yres - 1; - lcdfb_update(priv, &rect); + ret = lcdfb_update(priv, &rect); + if (ret < 0) + { + lcderr("FB update failed: %d\n", ret); + } /* Turn the LCD on at 75% power */ @@ -717,6 +729,7 @@ void nx_notify_rectangle(FAR NX_PLANEINFOTYPE *pinfo, { FAR struct fb_planeinfo_s *fpinfo = (FAR struct fb_planeinfo_s *)pinfo; FAR struct lcdfb_dev_s *priv; + int ret; DEBUGASSERT(fpinfo != NULL && rect != NULL); @@ -729,7 +742,11 @@ void nx_notify_rectangle(FAR NX_PLANEINFOTYPE *pinfo, priv = lcdfb_find(fpinfo->display); if (priv != NULL) { - lcdfb_update(priv, rect); + ret = lcdfb_update(priv, rect); + if (ret < 0) + { + lcderr("FB update failed: %d\n", ret); + } } } #endif diff --git a/drivers/lcd/ssd1306.h b/drivers/lcd/ssd1306.h index 787ec92312..e4cacfc8e1 100644 --- a/drivers/lcd/ssd1306.h +++ b/drivers/lcd/ssd1306.h @@ -304,8 +304,8 @@ struct ssd1306_dev_s * Public Function Prototypes **************************************************************************************/ -void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval); -void ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len); +int ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval); +int ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len); #ifdef CONFIG_LCD_SSD1306_SPI void ssd1306_select(FAR struct ssd1306_dev_s *priv, bool cs); diff --git a/drivers/lcd/ssd1306_base.c b/drivers/lcd/ssd1306_base.c index 6c98742264..56206f9198 100644 --- a/drivers/lcd/ssd1306_base.c +++ b/drivers/lcd/ssd1306_base.c @@ -4,7 +4,7 @@ * Univision SSD1306 controller in SPI mode and Densitron DD-12864WO-4A with SSD1309 * in SPI mode. * - * Copyright (C) 2012-2013, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013, 2015, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -175,14 +175,14 @@ static int ssd1306_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, /* LCD Specific Controls */ -static int ssd1306_getpower(struct lcd_dev_s *dev); -static int ssd1306_setpower(struct lcd_dev_s *dev, int power); -static int ssd1306_getcontrast(struct lcd_dev_s *dev); -static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); +static int ssd1306_getpower(struct lcd_dev_s *dev); +static int ssd1306_setpower(struct lcd_dev_s *dev, int power); +static int ssd1306_getcontrast(struct lcd_dev_s *dev); +static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); -static void ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on); -static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv); -static void ssd1306_redrawfb(struct ssd1306_dev_s *priv); +static int ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on); +static int ssd1306_configuredisplay(struct ssd1306_dev_s *priv); +static int ssd1306_redrawfb(struct ssd1306_dev_s *priv); /************************************************************************************** * Private Data @@ -279,6 +279,7 @@ static int ssd1306_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buf uint8_t usrmask; int pixlen; uint8_t i; + int ret; lcdinfo("row: %d col: %d npixels: %d\n", row, col, npixels); DEBUGASSERT(buffer); @@ -433,12 +434,25 @@ static int ssd1306_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buf /* Set the starting position for the run */ /* Set the column address to the XOFFSET value */ - ssd1306_sendbyte(priv, SSD1306_SETCOLL(devcol & 0x0f)); - ssd1306_sendbyte(priv, SSD1306_SETCOLH(devcol >> 4)); + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLL(devcol & 0x0f)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLH(devcol >> 4)); + if (ret < 0) + { + return ret; + } /* Set the page address */ - ssd1306_sendbyte(priv, SSD1306_PAGEADDR(page)); + ret = ssd1306_sendbyte(priv, SSD1306_PAGEADDR(page)); + if (ret < 0) + { + return ret; + } /* Select data transfer */ @@ -446,7 +460,11 @@ static int ssd1306_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buf /* Then transfer all of the data */ - ssd1306_sendblk(priv, fbptr, pixlen); + ret = ssd1306_sendblk(priv, fbptr, pixlen); + if (ret < 0) + { + return ret; + } /* De-select and unlock the device */ @@ -680,8 +698,10 @@ static int ssd1306_getpower(FAR struct lcd_dev_s *dev) * **************************************************************************************/ -static void ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on) +static int ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on) { + int ret; + /* Lock and select device */ ssd1306_select(priv, true); @@ -692,12 +712,14 @@ static void ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on) /* Turn the display on/off */ - (void)ssd1306_sendbyte(priv, (on ? SSD1306_DISPON : SSD1306_DISPOFF)); + ret = ssd1306_sendbyte(priv, (on ? SSD1306_DISPON : SSD1306_DISPOFF)); /* De-select and unlock the device */ ssd1306_cmddata(priv, false); ssd1306_select(priv, false); + + return ret; } /************************************************************************************** @@ -712,15 +734,21 @@ static void ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on) static int ssd1306_setpower(FAR struct lcd_dev_s *dev, int power) { struct ssd1306_dev_s *priv = (struct ssd1306_dev_s *)dev; - DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER); + int ret; lcdinfo("power: %d [%d]\n", power, priv->on ? CONFIG_LCD_MAXPOWER : 0); + DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER); if (power <= 0) { /* Turn the display off */ - ssd1306_do_disponoff(priv, false); + ret = ssd1306_do_disponoff(priv, false); + if (ret < 0) + { + return ret; + } + priv->on = false; /* Try turn off power completely */ @@ -750,17 +778,26 @@ static int ssd1306_setpower(FAR struct lcd_dev_s *dev, int power) { /* Configure display and turn the display on */ - ssd1306_configuredisplay(priv); + ret = ssd1306_configuredisplay(priv); + if (ret < 0) + { + return ret; + } /* Draw the framebuffer */ - ssd1306_redrawfb(priv); + ret = ssd1306_redrawfb(priv); } else { /* Turn the display on */ - ssd1306_do_disponoff(priv, true); + ret = ssd1306_do_disponoff(priv, true); + } + + if (ret < 0) + { + return ret; } priv->on = true; @@ -798,6 +835,7 @@ static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) { struct ssd1306_dev_s *priv = (struct ssd1306_dev_s *)dev; unsigned int scaled; + int ret; lcdinfo("contrast: %d\n", contrast); DEBUGASSERT(priv); @@ -831,8 +869,18 @@ static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) /* Set the contrast */ - (void)ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Set contrast control register */ - (void)ssd1306_sendbyte(priv, SSD1306_CONTRAST(scaled)); /* Data 1: Set 1 of 256 contrast steps */ + ret = ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Set contrast control register */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CONTRAST(scaled)); /* Data 1: Set 1 of 256 contrast steps */ + if (ret < 0) + { + return ret; + } + priv->contrast = contrast; /* De-select and unlock the device */ @@ -849,8 +897,10 @@ static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) * **************************************************************************************/ -static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv) +static int ssd1306_configuredisplay(struct ssd1306_dev_s *priv) { + int ret; + /* Lock and select device */ ssd1306_select(priv, true); @@ -867,74 +917,340 @@ static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv) #ifdef IS_SSD1309 - ssd1306_sendbyte(priv, SSD1309_PROTOFF); /* Unlock driver IC */ - ssd1306_sendbyte(priv, SSD1306_DISPOFF); /* Display off 0xae */ - ssd1306_sendbyte(priv, SSD1309_SETMEMORY); /* Set page addressing mode: 0x0, 0x01 or 0x02 */ - ssd1306_sendbyte(priv, SSD1309_MEMADDR(0x02)); - ssd1306_sendbyte(priv, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */ - ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */ - ssd1306_sendbyte(priv, SSD1306_STARTLINE(0)); /* Set display start line 0x40 */ - ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0)); /* Set page address (Can ignore) */ - ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Contrast control 0x81 */ - ssd1306_sendbyte(priv ,SSD1306_CONTRAST(SSD1309_DEV_CONTRAST)); /* Default contrast 0xff */ - ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xa1 */ - ssd1306_sendbyte(priv, SSD1306_EDISPOFF); /* Normal display off 0xa4 (Can ignore) */ - ssd1306_sendbyte(priv, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xa6 */ - ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xa8 */ - ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY)); /* Duty = 1/64 or 1/32 */ - ssd1306_sendbyte(priv, SSD1306_SCANFROMCOM0); /* Com scan direction: Scan from COM[0] to COM[n-1] */ - ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE); /* Set display offset 0xd3 */ - ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0)); - ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET); /* Set clock divider 0xd5 */ - ssd1306_sendbyte(priv, SSD1306_CLKDIV(7,0)); /* 0x70 */ + ret = ssd1306_sendbyte(priv, SSD1309_PROTOFF); /* Unlock driver IC */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET); /* Set pre-charge period 0xd9 */ - ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f,0x0a)); /* 0xfa: Fh cycles for discharge and Ah cycles for pre-charge */ + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFF); /* Display off 0xae */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xda */ - ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */ + ret = ssd1306_sendbyte(priv, SSD1309_SETMEMORY); /* Set page addressing mode: 0x0, 0x01 or 0x02 */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_VCOM_SET); /* set vcomh 0xdb */ - ssd1306_sendbyte(priv, SSD1306_VCOM(0x3C)); + ret = ssd1306_sendbyte(priv, SSD1309_MEMADDR(0x02)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_STARTLINE(0)); /* Set display start line 0x40 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0)); /* Set page address (Can ignore) */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Contrast control 0x81 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv ,SSD1306_CONTRAST(SSD1309_DEV_CONTRAST)); /* Default contrast 0xff */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xa1 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_EDISPOFF); /* Normal display off 0xa4 (Can ignore) */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xa6 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xa8 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY)); /* Duty = 1/64 or 1/32 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_SCANFROMCOM0); /* Com scan direction: Scan from COM[0] to COM[n-1] */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE); /* Set display offset 0xd3 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET); /* Set clock divider 0xd5 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CLKDIV(7,0)); /* 0x70 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET); /* Set pre-charge period 0xd9 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f,0x0a)); /* 0xfa: Fh cycles for discharge and Ah cycles for pre-charge */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xda */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_VCOM_SET); /* set vcomh 0xdb */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_VCOM(0x3C)); + if (ret < 0) + { + return ret; + } #else - ssd1306_sendbyte(priv, SSD1306_DISPOFF); /* Display off 0xae */ - ssd1306_sendbyte(priv, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */ - ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */ - ssd1306_sendbyte(priv, SSD1306_STARTLINE(0)); /* Set display start line 0x40 */ - //ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0)); /* Set page address (Can ignore) */ - ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Contrast control 0x81 */ - ssd1306_sendbyte(priv, SSD1306_CONTRAST(SSD1306_DEV_CONTRAST)); /* Default contrast 0xCF */ - ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xa1 */ - //ssd1306_sendbyte(priv, SSD1306_EDISPOFF); /* Normal display off 0xa4 (Can ignore) */ - ssd1306_sendbyte(priv, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xa6 */ - ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xa8 */ - ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY)); /* Duty = 1/64 or 1/32 */ - //ssd1306_sendbyte(priv, SSD1306_SCANTOCOM0); /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore) */ - ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE); /* Set display offset 0xd3 */ - ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0)); - ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET); /* Set clock divider 0xd5 */ - ssd1306_sendbyte(priv, SSD1306_CLKDIV(8, 0)); /* 0x80 */ + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFF); /* Display off 0xae */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET); /* Set pre-charge period 0xd9 */ - ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f, 1)); /* 0xf1 or 0x22 Enhanced mode */ + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xda */ - ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */ + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */ + if (ret < 0) + { + return ret; + } - ssd1306_sendbyte(priv, SSD1306_VCOM_SET); /* set vcomh 0xdb */ - ssd1306_sendbyte(priv, SSD1306_VCOM(0x40)); - - ssd1306_sendbyte(priv, SSD1306_CHRPUMP_SET); /* Set Charge Pump enable/disable 0x8d ssd1306 */ - ssd1306_sendbyte(priv, SSD1306_CHRPUMP_ON); /* 0x14 close 0x10 */ - - //ssd1306_sendbyte(priv, SSD1306_DCDC_MODE); /* DC/DC control mode: on (SSD1306 Not supported) */ - //ssd1306_sendbyte(priv, SSD1306_DCDC_ON); + ret = ssd1306_sendbyte(priv, SSD1306_STARTLINE(0)); /* Set display start line 0x40 */ + if (ret < 0) + { + return ret; + } +#if 0 + ret = ssd1306_sendbyte(priv, SSD1306_PAGEADDR(0)); /* Set page address (Can ignore) */ + if (ret < 0) + { + return ret; + } #endif - ssd1306_sendbyte(priv, SSD1306_DISPON); /* Display ON 0xaf */ + ret = ssd1306_sendbyte(priv, SSD1306_CONTRAST_MODE); /* Contrast control 0x81 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CONTRAST(SSD1306_DEV_CONTRAST)); /* Default contrast 0xCF */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xa1 */ + if (ret < 0) + { + return ret; + } + +#if 0 + ret = ssd1306_sendbyte(priv, SSD1306_EDISPOFF); /* Normal display off 0xa4 (Can ignore) */ + if (ret < 0) + { + return ret; + } +#endif + + ret = ssd1306_sendbyte(priv, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xa6 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xa8 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_MRATIO(SSD1306_DEV_DUTY)); /* Duty = 1/64 or 1/32 */ + if (ret < 0) + { + return ret; + } + +#if 0 + ret = ssd1306_sendbyte(priv, SSD1306_SCANTOCOM0); /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore) */ + if (ret < 0) + { + return ret; + } +#endif + + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFFS_MODE); /* Set display offset 0xd3 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_DISPOFFS(0)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CLKDIV_SET); /* Set clock divider 0xd5 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CLKDIV(8, 0)); /* 0x80 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRGPER_SET); /* Set pre-charge period 0xd9 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRGPER(0x0f, 1)); /* 0xf1 or 0x22 Enhanced mode */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xda */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CMNPAD(SSD1306_DEV_CMNPAD)); /* 0x12 or 0x02 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_VCOM_SET); /* set vcomh 0xdb */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_VCOM(0x40)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRPUMP_SET); /* Set Charge Pump enable/disable 0x8d ssd1306 */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_CHRPUMP_ON); /* 0x14 close 0x10 */ + if (ret < 0) + { + return ret; + } + +#if 0 + ret = ssd1306_sendbyte(priv, SSD1306_DCDC_MODE); /* DC/DC control mode: on (SSD1306 Not supported) */ + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_DCDC_ON); + if (ret < 0) + { + return ret; + } +#endif +#endif + + ret = ssd1306_sendbyte(priv, SSD1306_DISPON); /* Display ON 0xaf */ + if (ret < 0) + { + return ret; + } /* De-select and unlock the device */ @@ -943,6 +1259,7 @@ static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv) up_mdelay(100); priv->is_conf = true; + return OK; } /************************************************************************************** @@ -959,9 +1276,10 @@ static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv) * **************************************************************************************/ -static void ssd1306_redrawfb(struct ssd1306_dev_s *priv) +static int ssd1306_redrawfb(struct ssd1306_dev_s *priv) { unsigned int page; + int ret; /* Lock and select device */ @@ -977,12 +1295,25 @@ static void ssd1306_redrawfb(struct ssd1306_dev_s *priv) /* Set the column address to the XOFFSET value */ - ssd1306_sendbyte(priv, SSD1306_SETCOLL(SSD1306_DEV_XOFFSET)); - ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLL(SSD1306_DEV_XOFFSET)); + if (ret < 0) + { + return ret; + } + + ret = ssd1306_sendbyte(priv, SSD1306_SETCOLH(0)); + if (ret < 0) + { + return ret; + } /* Set the page address */ - ssd1306_sendbyte(priv, SSD1306_PAGEADDR(page)); + ret = ssd1306_sendbyte(priv, SSD1306_PAGEADDR(page)); + if (ret < 0) + { + return ret; + } /* Select data transfer */ @@ -990,13 +1321,18 @@ static void ssd1306_redrawfb(struct ssd1306_dev_s *priv) /* Transfer one page of the selected color */ - ssd1306_sendblk(priv, &priv->fb[page * SSD1306_DEV_XRES], - SSD1306_DEV_XRES); + ret = ssd1306_sendblk(priv, &priv->fb[page * SSD1306_DEV_XRES], + SSD1306_DEV_XRES); + if (ret < 0) + { + return ret; + } } /* De-select and unlock the device */ ssd1306_select(priv, false); + return OK; } /************************************************************************************** @@ -1087,7 +1423,7 @@ FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, * **************************************************************************************/ -void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color) +int ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color) { FAR struct ssd1306_dev_s *priv = (struct ssd1306_dev_s *)dev; @@ -1108,7 +1444,7 @@ void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color) /* Draw the framebuffer */ - ssd1306_redrawfb(priv); + return ssd1306_redrawfb(priv); } #endif /* CONFIG_LCD_SSD1306 */ diff --git a/drivers/lcd/ssd1306_i2c.c b/drivers/lcd/ssd1306_i2c.c index 7b134436d9..82240ddf08 100644 --- a/drivers/lcd/ssd1306_i2c.c +++ b/drivers/lcd/ssd1306_i2c.c @@ -64,7 +64,7 @@ * ****************************************************************************/ -void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) +int ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) { /* 8-bit data read sequence: * @@ -102,6 +102,8 @@ void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) { lcderr("ERROR: I2C_TRANSFER failed: %d\n", ret); } + + return ret; } /**************************************************************************** @@ -112,7 +114,7 @@ void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) * ****************************************************************************/ -void ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len) +int ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len) { struct i2c_msg_s msg[2]; uint8_t transfer_mode; @@ -146,6 +148,8 @@ void ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len) { lcderr("ERROR: I2C_TRANSFER failed: %d\n", ret); } + + return ret; } #endif /* CONFIG_LCD_SSD1306 &7 CONFIG_LCD_SSD1306_I2C */ diff --git a/drivers/lcd/ssd1306_spi.c b/drivers/lcd/ssd1306_spi.c index e7a59b7cbf..66c958ca38 100644 --- a/drivers/lcd/ssd1306_spi.c +++ b/drivers/lcd/ssd1306_spi.c @@ -82,7 +82,7 @@ void ssd1306_configspi(FAR struct spi_dev_s *spi) * ****************************************************************************/ -void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) +int ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) { #ifdef CONFIG_LCD_SSD1306_REGDEBUG _err("->0x%02x\n", regval); @@ -91,6 +91,7 @@ void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) /* Send byte value to display */ (void)SPI_SEND(priv->spi, regval); + return OK; } /**************************************************************************** @@ -101,11 +102,12 @@ void ssd1306_sendbyte(FAR struct ssd1306_dev_s *priv, uint8_t regval) * ****************************************************************************/ -void ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len) +int ssd1306_sendblk(FAR struct ssd1306_dev_s *priv, uint8_t *data, uint8_t len) { /* Send byte value to display */ (void)SPI_SNDBLOCK(priv->spi, data, len); + return OK; } /**************************************************************************** diff --git a/include/nuttx/lcd/ssd1306.h b/include/nuttx/lcd/ssd1306.h index 9a8433c68a..7c5665c72a 100644 --- a/include/nuttx/lcd/ssd1306.h +++ b/include/nuttx/lcd/ssd1306.h @@ -5,7 +5,7 @@ * Univision SSD1306 controller in SPI mode and Densitron DD-12864WO-4A with SSD1309 * in SPI mode. * - * Copyright (C) 2012-2013, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2012-2013, 2015, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * References: @@ -273,7 +273,7 @@ FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, * **************************************************************************************/ -void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color); +int ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color); #ifdef __cplusplus }