drivers/lcd: ssd1306: add support for board power control. ThingseeOne has regulator for controlling display power on/off. Patch adds support for board based power control to SSD1306 driver.

This commit is contained in:
Jussi Kivilinna 2017-08-22 08:40:27 -06:00 committed by Gregory Nutt
parent 310a29227a
commit 3dfeb9e59f
8 changed files with 214 additions and 86 deletions

View File

@ -153,7 +153,7 @@ FAR struct lcd_dev_s *board_graphics_setup(unsigned int devno)
{
/* Bind the SPI port to the OLED */
dev = ssd1306_initialize(spi, devno);
dev = ssd1306_initialize(spi, NULL, devno);
if (!dev)
{
lcderr("ERROR: Failed to bind SPI port 1 to OLED %d: %d\n", devno);

View File

@ -183,7 +183,7 @@ FAR struct lcd_dev_s *board_graphics_setup(unsigned int devno)
{
/* Bind the SPI port to the OLED */
dev = ssd1306_initialize(spi, devno);
dev = ssd1306_initialize(spi, NULL, devno);
if (!dev)
{
lcderr("ERROR: Failed to bind SPI port 1 to OLED %d: %d\n", devno);

View File

@ -183,7 +183,7 @@ FAR struct lcd_dev_s *board_graphics_setup(unsigned int devno)
{
/* Bind the SPI port to the OLED */
dev = ssd1306_initialize(spi, devno);
dev = ssd1306_initialize(spi, NULL, devno);
if (!dev)
{
lcderr("ERROR: Failed to bind SPI port 1 to OLED %d: %d\n", devno);

View File

@ -183,7 +183,7 @@ FAR struct lcd_dev_s *board_graphics_setup(unsigned int devno)
{
/* Bind the SPI port to the OLED */
dev = ssd1306_initialize(spi, devno);
dev = ssd1306_initialize(spi, NULL, devno);
if (!dev)
{
lcderr("ERROR: Failed to bind SPI port 1 to OLED %d: %d\n", devno);

View File

@ -132,7 +132,7 @@ FAR struct lcd_dev_s *board_graphics_setup(unsigned int devno)
{
/* Bind the SPI port to the OLED */
dev = ssd1306_initialize(spi, devno);
dev = ssd1306_initialize(spi, NULL, devno);
if (!dev)
{
lcderr("ERROR: Failed to bind SPI port 1 to OLED %d: %d\n", devno);

View File

@ -280,6 +280,9 @@ struct ssd1306_dev_s
#endif
uint8_t contrast; /* Current contrast setting */
bool on; /* true: display is on */
bool is_conf; /* true: display had been configured */
FAR const struct ssd1306_priv_s *board_priv; /* Board specific structure */
/* The SSD1306 does not support reading from the display memory in SPI mode.
* Since there is 1 BPP and access is byte-by-byte, it is necessary to keep

View File

@ -180,6 +180,10 @@ 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);
/**************************************************************************************
* Private Data
**************************************************************************************/
@ -669,6 +673,34 @@ static int ssd1306_getpower(FAR struct lcd_dev_s *dev)
return priv->on ? CONFIG_LCD_MAXPOWER : 0;
}
/**************************************************************************************
* Name: ssd1306_do_disponoff
*
* Description:
* Enable/disable LCD panel power
*
**************************************************************************************/
static void ssd1306_do_disponoff(struct ssd1306_dev_s *priv, bool on)
{
/* Lock and select device */
ssd1306_select(priv, true);
/* Select command transfer */
ssd1306_cmddata(priv, true);
/* Turn the display on/off */
(void)ssd1306_sendbyte(priv, (on ? SSD1306_DISPON : SSD1306_DISPOFF));
/* De-select and unlock the device */
ssd1306_cmddata(priv, false);
ssd1306_select(priv, false);
}
/**************************************************************************************
* Name: ssd1306_setpower
*
@ -685,28 +717,56 @@ static int ssd1306_setpower(FAR struct lcd_dev_s *dev, int power)
lcdinfo("power: %d [%d]\n", power, priv->on ? CONFIG_LCD_MAXPOWER : 0);
/* Lock and select device */
ssd1306_select(priv, true);
if (power <= 0)
{
/* Turn the display off */
(void)ssd1306_sendbyte(priv, SSD1306_DISPOFF);
ssd1306_do_disponoff(priv, false);
priv->on = false;
/* Try turn off power completely */
if (priv->board_priv && priv->board_priv->set_vcc)
{
/* Do power off. */
if (priv->board_priv->set_vcc(false))
{
/* Display is completely powered off, not configured anymore. */
priv->is_conf = false;
}
}
}
else
{
/* Turn the display on */
if (priv->board_priv && priv->board_priv->set_vcc)
{
/* Do power on. */
(void)priv->board_priv->set_vcc(true);
}
if (!priv->is_conf)
{
/* Configure display and turn the display on */
ssd1306_configuredisplay(priv);
/* Draw the framebuffer */
ssd1306_redrawfb(priv);
}
else
{
/* Turn the display on */
ssd1306_do_disponoff(priv, true);
}
(void)ssd1306_sendbyte(priv, SSD1306_DISPON);
priv->on = true;
}
/* De-select and unlock the device */
ssd1306_select(priv, false);
return OK;
}
@ -783,55 +843,15 @@ static int ssd1306_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
}
/**************************************************************************************
* Public Functions
**************************************************************************************/
/**************************************************************************************
* Name: ssd1306_initialize
* Name: ssd1306_configuredisplay
*
* Description:
* Initialize the UG-2864HSWEG01 video hardware. The initial state of the
* OLED is fully initialized, display memory cleared, and the OLED ready
* to use, but with the power setting at 0 (full off == sleep mode).
*
* Input Parameters:
*
* spi - A reference to the SPI driver instance.
* devno - A value in the range of 0 through CONFIG_SSD1306_NINTERFACES-1.
* This allows support for multiple OLED devices.
*
* Returned Value:
*
* On success, this function returns a reference to the LCD object for
* the specified OLED. NULL is returned on any failure.
* Setup LCD display.
*
**************************************************************************************/
#ifdef CONFIG_LCD_SSD1306_SPI
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct spi_dev_s *dev, unsigned int devno)
#else
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, unsigned int devno)
#endif
static void ssd1306_configuredisplay(struct ssd1306_dev_s *priv)
{
FAR struct ssd1306_dev_s *priv = &g_oleddev;
lcdinfo("Initializing\n");
DEBUGASSERT(dev && devno == 0);
#ifdef CONFIG_LCD_SSD1306_SPI
priv->spi = dev;
/* Configure the SPI */
ssd1306_configspi(priv->spi);
#else
/* Remember the I2C configuration */
priv->i2c = dev;
priv->addr = CONFIG_SSD1306_I2CADDR;
#endif
/* Lock and select device */
ssd1306_select(priv, true);
@ -921,19 +941,16 @@ FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, unsigned
ssd1306_select(priv, false);
/* Clear the display */
up_mdelay(100);
ssd1306_fill(&priv->dev, CONFIG_NX_BGCOLOR);
return &priv->dev;
priv->is_conf = true;
}
/**************************************************************************************
* Name: ssd1306_fill
* Name: ssd1306_redrawfb
*
* Description:
* This non-standard method can be used to clear the entire display by writing one
* color to the display. This is much faster than writing a series of runs.
* Redraw full framebuffer to display
*
* Input Parameters:
* priv - Reference to private driver structure
@ -943,26 +960,10 @@ FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, unsigned
*
**************************************************************************************/
void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color)
static void ssd1306_redrawfb(struct ssd1306_dev_s *priv)
{
FAR struct ssd1306_dev_s *priv = &g_oleddev;
unsigned int page;
/* Make an 8-bit version of the selected color */
if (color & 1)
{
color = 0xff;
}
else
{
color = 0;
}
/* Initialize the framebuffer */
memset(priv->fb, color, SSD1306_DEV_FBSIZE);
/* Lock and select device */
ssd1306_select(priv, true);
@ -999,4 +1000,114 @@ void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color)
ssd1306_select(priv, false);
}
/**************************************************************************************
* Public Functions
**************************************************************************************/
/**************************************************************************************
* Name: ssd1306_initialize
*
* Description:
* Initialize the UG-2864HSWEG01 video hardware. The initial state of the
* OLED is fully initialized, display memory cleared, and the OLED ready
* to use, but with the power setting at 0 (full off == sleep mode).
*
* Input Parameters:
*
* spi - A reference to the SPI driver instance.
* devno - A value in the range of 0 through CONFIG_SSD1306_NINTERFACES-1.
* This allows support for multiple OLED devices.
*
* Returned Value:
*
* On success, this function returns a reference to the LCD object for
* the specified OLED. NULL is returned on any failure.
*
**************************************************************************************/
#ifdef CONFIG_LCD_SSD1306_SPI
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct spi_dev_s *dev,
FAR const struct ssd1306_priv_s *board_priv,
unsigned int devno)
#else
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev,
FAR const struct ssd1306_priv_s *board_priv,
unsigned int devno)
#endif
{
FAR struct ssd1306_dev_s *priv = &g_oleddev;
DEBUGASSERT(dev && devno == 0);
priv->on = false;
priv->is_conf = false;
/* Register board specific functions */
priv->board_priv = board_priv;
#ifdef CONFIG_LCD_SSD1306_SPI
priv->spi = dev;
/* Configure the SPI */
ssd1306_configspi(priv->spi);
#else
/* Remember the I2C configuration */
priv->i2c = dev;
priv->addr = CONFIG_SSD1306_I2CADDR;
#endif
/* Initialize the framebuffer */
memset(priv->fb, SSD1306_Y1_BLACK & 1 ? 0xff : 0x00, SSD1306_DEV_FBSIZE);
/* Power on and configure display */
ssd1306_setpower(&priv->dev, true);
return &priv->dev;
}
/**************************************************************************************
* Name: ssd1306_fill
*
* Description:
* This non-standard method can be used to clear the entire display by writing one
* color to the display. This is much faster than writing a series of runs.
*
* Input Parameters:
* priv - Reference to private driver structure
*
* Assumptions:
* Caller has selected the OLED section.
*
**************************************************************************************/
void ssd1306_fill(FAR struct lcd_dev_s *dev, uint8_t color)
{
FAR struct ssd1306_dev_s *priv = (struct ssd1306_dev_s *)dev;
/* Make an 8-bit version of the selected color */
if (color & 1)
{
color = 0xff;
}
else
{
color = 0;
}
/* Initialize the framebuffer */
memset(priv->fb, color, SSD1306_DEV_FBSIZE);
/* Draw the framebuffer */
ssd1306_redrawfb(priv);
}
#endif /* CONFIG_LCD_SSD1306 */

View File

@ -1,8 +1,9 @@
/**************************************************************************************
* include/nuttx/lcd/ug-2864hsweg01.h
* include/nuttx/lcd/ssd1306.h
*
* Driver for Univision UG-2864HSWEG01 OLED display or UG-2832HSWEG04 both with the
* Univision SSD1306 controller in SPI mode
* 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.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -14,6 +15,8 @@
* Doc No.: SAS1-B020-B, Univision Technology Inc.
* 3. SSD1306, 128 X 64 Dot Matrix OLED/PLED, Preliminary Segment/Common Driver with
* Controller, Solomon Systech
* 4. SSD1309, 128 x 64 Dot Matrix OLED/PLED Segment/Common Driver with Controller,
* Solomon Systech
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -200,6 +203,12 @@
* Public Types
**************************************************************************************/
struct ssd1306_priv_s
{
bool (*set_vcc) (bool on); /* Allow board to control display power. Return true if
request state set successfully. */
};
/**************************************************************************************
* Public Data
**************************************************************************************/
@ -224,6 +233,7 @@ extern "C"
* Input Parameters:
*
* dev - A reference to the SPI/I2C driver instance.
* board_priv - Board specific structure.
* devno - A value in the range of 0 through CONFIG_UG2864HSWEG01_NINTERFACES-1.
* This allows support for multiple OLED devices.
*
@ -237,9 +247,13 @@ extern "C"
struct lcd_dev_s; /* See include/nuttx/lcd/lcd.h */
struct spi_dev_s; /* See include/nuttx/spi/spi.h */
#ifdef CONFIG_LCD_SSD1306_SPI
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct spi_dev_s *dev, unsigned int devno);
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct spi_dev_s *dev,
FAR const struct ssd1306_priv_s *board_priv,
unsigned int devno);
#else
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev, unsigned int devno);
FAR struct lcd_dev_s *ssd1306_initialize(FAR struct i2c_master_s *dev,
FAR const struct ssd1306_priv_s *board_priv,
unsigned int devno);
#endif
/************************************************************************************************