drivers: add SSD1306 display controller driver
Add SSD1306 OLED display controller driver. Signed-off-by: Johann Fischer <j.fischer@phytec.de>
This commit is contained in:
parent
f531e0d62e
commit
419f4b7801
6 changed files with 696 additions and 0 deletions
|
@ -6,3 +6,4 @@ zephyr_sources_ifdef(CONFIG_ILI9340 display_ili9340.c)
|
|||
zephyr_sources_ifdef(CONFIG_ILI9340_LCD_ADAFRUIT_1480
|
||||
display_ili9340_adafruit_1480.c
|
||||
)
|
||||
zephyr_sources_ifdef(CONFIG_SSD1306 ssd1306.c)
|
||||
|
|
|
@ -21,4 +21,6 @@ source "drivers/display/Kconfig.microbit"
|
|||
|
||||
source "drivers/display/Kconfig.ili9340"
|
||||
|
||||
source "drivers/display/Kconfig.ssd1306"
|
||||
|
||||
endif # DISPLAY
|
||||
|
|
38
drivers/display/Kconfig.ssd1306
Normal file
38
drivers/display/Kconfig.ssd1306
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Kconfig - SSD1306 display controller configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2018 Phytec Messtechnik GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig SSD1306
|
||||
bool "SSD1306 display driver"
|
||||
depends on I2C
|
||||
help
|
||||
Enable driver for SSD1306 display driver.
|
||||
|
||||
if SSD1306
|
||||
|
||||
config SSD1306_DEFAULT_CONTRAST
|
||||
int "SSD1306 default contrast"
|
||||
default 128
|
||||
range 0 255
|
||||
help
|
||||
SSD1673 default contrast.
|
||||
|
||||
choice
|
||||
prompt "Display controller type"
|
||||
default SSD1306_DEFAULT
|
||||
help
|
||||
Specify the type of the controller.
|
||||
|
||||
config SSD1306_DEFAULT
|
||||
bool "Default SSD1306 controller"
|
||||
|
||||
config SSD1306_SH1106_COMPATIBLE
|
||||
bool "Enable SH1106 compatible mode"
|
||||
|
||||
endchoice
|
||||
|
||||
endif #SSD1306
|
478
drivers/display/ssd1306.c
Normal file
478
drivers/display/ssd1306.c
Normal file
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
* Copyright (c) 2018 PHYTEC Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(ssd1306);
|
||||
|
||||
#include <string.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <gpio.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#include "ssd1306_regs.h"
|
||||
#include <display/cfb.h>
|
||||
|
||||
#if !defined(CONFIG_SSD1306_I2C_MASTER_DEV_NAME)
|
||||
#if defined(I2C_0_SSD1306_BUS_NAME)
|
||||
#define CONFIG_SSD1306_I2C_MASTER_DEV_NAME I2C_0_SSD1306_BUS_NAME
|
||||
#elif defined(I2C_1_SSD1306_BUS_NAME)
|
||||
#define CONFIG_SSD1306_I2C_MASTER_DEV_NAME I2C_1_SSD1306_BUS_NAME
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_SSD1306_I2C_ADDR)
|
||||
#if defined(I2C_0_SSD1306_BASE_ADDRESS)
|
||||
#define CONFIG_SSD1306_I2C_ADDR I2C_0_SSD1306_BASE_ADDRESS
|
||||
#elif defined(I2C_1_SSD1306_BASE_ADDRESS)
|
||||
#define CONFIG_SSD1306_I2C_ADDR I2C_1_SSD1306_BASE_ADDRESS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_SSD1306_DEV_NAME)
|
||||
#if defined(I2C_0_SSD1306_LABEL)
|
||||
#define CONFIG_SSD1306_DEV_NAME I2C_0_SSD1306_LABEL
|
||||
#elif defined(I2C_1_SSD1306_LABEL)
|
||||
#define CONFIG_SSD1306_DEV_NAME I2C_1_SSD1306_LABEL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(I2C_0_SSD1306_HEIGHT)
|
||||
#define SSD1306_PANEL_WIDTH I2C_0_SSD1306_WIDTH
|
||||
#define SSD1306_PANEL_HEIGHT I2C_0_SSD1306_HEIGHT
|
||||
#define SSD1306_PANEL_FIRST_SEG I2C_0_SSD1306_SEGMENT_OFFSET
|
||||
#define SSD1306_PANEL_DISPLAY_OFFSET I2C_0_SSD1306_DISPLAY_OFFSET
|
||||
#define SSD1306_PANEL_PAGE_OFFSET I2C_0_SSD1306_PAGE_OFFSET
|
||||
#define SSD1306_PANEL_PRECHARGE_PERIOD I2C_0_SSD1306_PRECHARGEP
|
||||
#endif
|
||||
|
||||
#if defined(I2C_1_SSD1306_HEIGHT)
|
||||
#define SSD1306_PANEL_WIDTH I2C_1_SSD1306_WIDTH
|
||||
#define SSD1306_PANEL_HEIGHT I2C_1_SSD1306_HEIGHT
|
||||
#define SSD1306_PANEL_FIRST_SEG I2C_1_SSD1306_SEGMENT_OFFSET
|
||||
#define SSD1306_PANEL_DISPLAY_OFFSET I2C_1_SSD1306_DISPLAY_OFFSET
|
||||
#define SSD1306_PANEL_PAGE_OFFSET I2C_1_SSD1306_PAGE_OFFSET
|
||||
#define SSD1306_PANEL_PRECHARGE_PERIOD I2C_1_SSD1306_PRECHARGEP
|
||||
#endif
|
||||
|
||||
#if defined(I2C_0_SSD1306_SEGMENT_REMAP)
|
||||
#define SSD1306_PANEL_SEGMENT_REMAP true
|
||||
#elif defined(I2C_1_SSD1306_SEGMENT_REMAP)
|
||||
#define SSD1306_PANEL_SEGMENT_REMAP true
|
||||
#else
|
||||
#define SSD1306_PANEL_SEGMENT_REMAP false
|
||||
#endif
|
||||
|
||||
#if defined(I2C_0_SSD1306_COM_INVDIR)
|
||||
#define SSD1306_PANEL_COM_INVDIR true
|
||||
#elif defined(I2C_1_SSD1306_COM_INVDIR)
|
||||
#define SSD1306_PANEL_COM_INVDIR true
|
||||
#else
|
||||
#define SSD1306_PANEL_COM_INVDIR false
|
||||
#endif
|
||||
|
||||
#define SSD1306_PANEL_NUMOF_PAGES (SSD1306_PANEL_HEIGHT / 8)
|
||||
#define SSD1306_CLOCK_DIV_RATIO 0x0
|
||||
#define SSD1306_CLOCK_FREQUENCY 0x8
|
||||
#define SSD1306_PANEL_MUX_RATIO 63
|
||||
#define SSD1306_PANEL_VCOM_DESEL_LEVEL 0x20
|
||||
#define SSD1306_PANEL_PUMP_VOLTAGE SSD1306_SET_PUMP_VOLTAGE_90
|
||||
|
||||
#if defined(CONFIG_SSD1306_SH1106_COMPATIBLE)
|
||||
#define SSD1306_PANEL_NUMOF_COLUMS 132
|
||||
#else
|
||||
#define SSD1306_PANEL_NUMOF_COLUMS 128
|
||||
#endif
|
||||
|
||||
#ifndef SSD1306_ADDRESSING_MODE
|
||||
#define SSD1306_ADDRESSING_MODE (SSD1306_SET_MEM_ADDRESSING_HORIZONTAL)
|
||||
#endif
|
||||
|
||||
struct ssd1306_data {
|
||||
struct device *i2c;
|
||||
u8_t contrast;
|
||||
u8_t scan_mode;
|
||||
};
|
||||
|
||||
static inline int ssd1306_reg_read(struct ssd1306_data *driver,
|
||||
u8_t reg, u8_t * const val)
|
||||
{
|
||||
return i2c_reg_read_byte(driver->i2c, CONFIG_SSD1306_I2C_ADDR,
|
||||
reg, val);
|
||||
}
|
||||
|
||||
static inline int ssd1306_reg_write(struct ssd1306_data *driver,
|
||||
u8_t reg, u8_t val)
|
||||
{
|
||||
return i2c_reg_write_byte(driver->i2c, CONFIG_SSD1306_I2C_ADDR,
|
||||
reg, val);
|
||||
}
|
||||
|
||||
static inline int ssd1306_reg_update(struct ssd1306_data *driver, u8_t reg,
|
||||
u8_t mask, u8_t val)
|
||||
{
|
||||
return i2c_reg_update_byte(driver->i2c, CONFIG_SSD1306_I2C_ADDR,
|
||||
reg, mask, val);
|
||||
}
|
||||
|
||||
static inline int ssd1306_set_panel_orientation(struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
(SSD1306_PANEL_SEGMENT_REMAP ?
|
||||
SSD1306_SET_SEGMENT_MAP_REMAPED :
|
||||
SSD1306_SET_SEGMENT_MAP_NORMAL),
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
(SSD1306_PANEL_COM_INVDIR ?
|
||||
SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED :
|
||||
SSD1306_SET_COM_OUTPUT_SCAN_NORMAL)
|
||||
};
|
||||
|
||||
return i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR);
|
||||
}
|
||||
|
||||
static inline int ssd1306_set_timing_setting(struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_CLOCK_DIV_RATIO,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
(SSD1306_CLOCK_FREQUENCY << 4) | SSD1306_CLOCK_DIV_RATIO,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_CHARGE_PERIOD,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_PANEL_PRECHARGE_PERIOD,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_VCOM_DESELECT_LEVEL,
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_PANEL_VCOM_DESEL_LEVEL
|
||||
};
|
||||
|
||||
return i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR);
|
||||
}
|
||||
|
||||
static inline int ssd1306_set_hardware_config(struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_START_LINE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_DISPLAY_OFFSET,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_PANEL_DISPLAY_OFFSET,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_PADS_HW_CONFIG,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_PADS_HW_ALTERNATIVE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_MULTIPLEX_RATIO,
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_PANEL_MUX_RATIO
|
||||
};
|
||||
|
||||
return i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR);
|
||||
}
|
||||
|
||||
static inline int ssd1306_set_charge_pump(const struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
#if defined(CONFIG_SSD1306_DEFAULT)
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_CHARGE_PUMP_ON,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_CHARGE_PUMP_ON_ENABLED,
|
||||
#endif
|
||||
#if defined(CONFIG_SSD1306_SH1106_COMPATIBLE)
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SH1106_SET_DCDC_MODE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SH1106_SET_DCDC_ENABLED,
|
||||
#endif
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_PANEL_PUMP_VOLTAGE,
|
||||
};
|
||||
|
||||
return i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR);
|
||||
}
|
||||
|
||||
int ssd1306_resume(const struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
/* set display on */
|
||||
return ssd1306_reg_write(driver, SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_DISPLAY_ON);
|
||||
}
|
||||
|
||||
int ssd1306_suspend(const struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
/* set display on */
|
||||
return ssd1306_reg_write(driver, SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_DISPLAY_OFF);
|
||||
}
|
||||
|
||||
int ssd1306_write_page(struct device *dev, u8_t page, void * const data,
|
||||
size_t length)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
#ifdef OLED_PANEL_CONTROLLER_SSD1306
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_MEM_ADDRESSING_MODE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_MEM_ADDRESSING_PAGE,
|
||||
#endif
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_LOWER_COL_ADDRESS |
|
||||
(SSD1306_PANEL_FIRST_SEG &
|
||||
SSD1306_SET_LOWER_COL_ADDRESS_MASK),
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_HIGHER_COL_ADDRESS |
|
||||
((SSD1306_PANEL_FIRST_SEG >> 4) &
|
||||
SSD1306_SET_LOWER_COL_ADDRESS_MASK),
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_SET_PAGE_START_ADDRESS | page
|
||||
};
|
||||
|
||||
if (page >= SSD1306_PANEL_NUMOF_PAGES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length > SSD1306_PANEL_NUMOF_COLUMS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return i2c_burst_write(driver->i2c, CONFIG_SSD1306_I2C_ADDR,
|
||||
SSD1306_CONTROL_LAST_BYTE_DATA,
|
||||
data, length);
|
||||
}
|
||||
|
||||
int ssd1306_write(const struct device *dev, const u16_t x, const u16_t y,
|
||||
const struct display_buffer_descriptor *desc,
|
||||
const void *buf)
|
||||
{
|
||||
if (desc->pitch < desc->width) {
|
||||
LOG_ERR("Pitch is smaller then width");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf == NULL || desc->buf_size == 0) {
|
||||
LOG_ERR("Display buffer is not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (desc->pitch > desc->width) {
|
||||
LOG_ERR("Unsupported mode");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x != 0 && y != 0) {
|
||||
LOG_ERR("Unsupported origin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SSD1306_DEFAULT)
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_MEM_ADDRESSING_MODE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_ADDRESSING_MODE,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_COLUMN_ADDRESS,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
0,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
(SSD1306_PANEL_NUMOF_COLUMS - 1),
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_PAGE_ADDRESS,
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
0,
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
(SSD1306_PANEL_NUMOF_PAGES - 1)
|
||||
};
|
||||
|
||||
if (i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR)) {
|
||||
LOG_ERR("Failed to write command");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return i2c_burst_write(driver->i2c, CONFIG_SSD1306_I2C_ADDR,
|
||||
SSD1306_CONTROL_LAST_BYTE_DATA,
|
||||
(u8_t *)buf, desc->buf_size);
|
||||
|
||||
#elif defined(CONFIG_SSD1306_SH1106_COMPATIBLE)
|
||||
if (len != SSD1306_PANEL_NUMOF_PAGES * SSD1306_PANEL_WIDTH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t pidx = 0; pidx < SSD1306_PANEL_NUMOF_PAGES; pidx++) {
|
||||
if (ssd1306_write_page(dev, pidx, buf, SSD1306_PANEL_WIDTH)) {
|
||||
return -1;
|
||||
}
|
||||
buf = (u8_t *)buf + SSD1306_PANEL_WIDTH;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_read(const struct device *dev, const u16_t x,
|
||||
const u16_t y,
|
||||
const struct display_buffer_descriptor *desc,
|
||||
void *buf)
|
||||
{
|
||||
LOG_ERR("Unsupported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static void *ssd1306_get_framebuffer(const struct device *dev)
|
||||
{
|
||||
LOG_ERR("Unsupported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ssd1306_set_brightness(const struct device *dev,
|
||||
const u8_t brightness)
|
||||
{
|
||||
LOG_WRN("Unsupported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int ssd1306_set_contrast(const struct device *dev, const u8_t contrast)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_CONTRAST_CTRL,
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
contrast,
|
||||
};
|
||||
|
||||
return i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR);
|
||||
}
|
||||
|
||||
static void ssd1306_get_capabilities(const struct device *dev,
|
||||
struct display_capabilities *caps)
|
||||
{
|
||||
memset(caps, 0, sizeof(struct display_capabilities));
|
||||
caps->x_resolution = SSD1306_PANEL_WIDTH;
|
||||
caps->y_resolution = SSD1306_PANEL_HEIGHT;
|
||||
caps->supported_pixel_formats = PIXEL_FORMAT_MONO10;
|
||||
caps->current_pixel_format = PIXEL_FORMAT_MONO10;
|
||||
caps->screen_info = SCREEN_INFO_MONO_VTILED;
|
||||
}
|
||||
|
||||
static int ssd1306_set_pixel_format(const struct device *dev,
|
||||
const enum display_pixel_format pf)
|
||||
{
|
||||
LOG_ERR("Unsupported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int ssd1306_init_device(struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
|
||||
u8_t cmd_buf[] = {
|
||||
SSD1306_CONTROL_BYTE_CMD,
|
||||
SSD1306_SET_ENTIRE_DISPLAY_OFF,
|
||||
SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_SET_NORMAL_DISPLAY,
|
||||
};
|
||||
|
||||
/* Turn display off */
|
||||
if (ssd1306_reg_write(driver, SSD1306_CONTROL_LAST_BYTE_CMD,
|
||||
SSD1306_DISPLAY_OFF)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssd1306_set_timing_setting(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssd1306_set_hardware_config(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssd1306_set_panel_orientation(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssd1306_set_charge_pump(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (i2c_write(driver->i2c, cmd_buf, sizeof(cmd_buf),
|
||||
CONFIG_SSD1306_I2C_ADDR)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ssd1306_set_contrast(dev, CONFIG_SSD1306_DEFAULT_CONTRAST)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ssd1306_resume(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_init(struct device *dev)
|
||||
{
|
||||
struct ssd1306_data *driver = dev->driver_data;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
driver->i2c = device_get_binding(CONFIG_SSD1306_I2C_MASTER_DEV_NAME);
|
||||
if (driver->i2c == NULL) {
|
||||
LOG_ERR("Failed to get pointer to %s device!",
|
||||
CONFIG_SSD1306_I2C_MASTER_DEV_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ssd1306_init_device(dev)) {
|
||||
LOG_ERR("Failed to initialize device!");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ssd1306_data ssd1306_driver;
|
||||
|
||||
static struct display_driver_api ssd1306_driver_api = {
|
||||
.blanking_on = ssd1306_resume,
|
||||
.blanking_off = ssd1306_suspend,
|
||||
.write = ssd1306_write,
|
||||
.read = ssd1306_read,
|
||||
.get_framebuffer = ssd1306_get_framebuffer,
|
||||
.set_brightness = ssd1306_set_brightness,
|
||||
.set_contrast = ssd1306_set_contrast,
|
||||
.get_capabilities = ssd1306_get_capabilities,
|
||||
.set_pixel_format = ssd1306_set_pixel_format,
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(ssd1306, CONFIG_SSD1306_DEV_NAME, ssd1306_init,
|
||||
&ssd1306_driver, NULL,
|
||||
POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY,
|
||||
&ssd1306_driver_api);
|
109
drivers/display/ssd1306_regs.h
Normal file
109
drivers/display/ssd1306_regs.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Phytec Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SSD1306_REGS_H__
|
||||
#define __SSD1306_REGS_H__
|
||||
|
||||
#define SSD1306_CONTROL_LAST_BYTE_CMD 0x00
|
||||
#define SSD1306_CONTROL_LAST_BYTE_DATA 0x40
|
||||
#define SSD1306_CONTROL_BYTE_CMD 0x80
|
||||
#define SSD1306_CONTROL_BYTE_DATA 0xc0
|
||||
#define SSD1306_READ_STATUS_MASK 0xc0
|
||||
#define SSD1306_READ_STATUS_BUSY 0x80
|
||||
#define SSD1306_READ_STATUS_ON 0x40
|
||||
|
||||
/*
|
||||
* Fundamental Command Table
|
||||
*/
|
||||
#define SSD1306_SET_CONTRAST_CTRL 0x81 /* double byte command */
|
||||
|
||||
#define SSD1306_SET_ENTIRE_DISPLAY_OFF 0xa4
|
||||
#define SSD1306_SET_ENTIRE_DISPLAY_ON 0xa5
|
||||
|
||||
#define SSD1306_SET_NORMAL_DISPLAY 0xa6
|
||||
#define SSD1306_SET_REVERSE_DISPLAY 0xa7
|
||||
|
||||
#define SSD1306_DISPLAY_OFF 0xae
|
||||
#define SSD1306_DISPLAY_ON 0xaf
|
||||
|
||||
/*
|
||||
* Addressing Setting Command Table
|
||||
*/
|
||||
#define SSD1306_SET_LOWER_COL_ADDRESS 0x00
|
||||
#define SSD1306_SET_LOWER_COL_ADDRESS_MASK 0x0f
|
||||
|
||||
#define SSD1306_SET_HIGHER_COL_ADDRESS 0x10
|
||||
#define SSD1306_SET_HIGHER_COL_ADDRESS_MASK 0x0f
|
||||
|
||||
#define SSD1306_SET_MEM_ADDRESSING_MODE 0x20 /* double byte command */
|
||||
#define SSD1306_SET_MEM_ADDRESSING_HORIZONTAL 0x00
|
||||
#define SSD1306_SET_MEM_ADDRESSING_VERTICAL 0x01
|
||||
#define SSD1306_SET_MEM_ADDRESSING_PAGE 0x02
|
||||
|
||||
#define SSD1306_SET_COLUMN_ADDRESS 0x21 /* triple byte command */
|
||||
|
||||
#define SSD1306_SET_PAGE_ADDRESS 0x22 /* triple byte command */
|
||||
|
||||
#define SSD1306_SET_PAGE_START_ADDRESS 0xb0
|
||||
#define SSD1306_SET_PAGE_START_ADDRESS_MASK 0x07
|
||||
|
||||
|
||||
/*
|
||||
* Hardware Configuration Command Table
|
||||
*/
|
||||
#define SSD1306_SET_START_LINE 0x40
|
||||
#define SSD1306_SET_START_LINE_MASK 0x3f
|
||||
|
||||
#define SSD1306_SET_SEGMENT_MAP_NORMAL 0xa0
|
||||
#define SSD1306_SET_SEGMENT_MAP_REMAPED 0xa1
|
||||
|
||||
#define SSD1306_SET_MULTIPLEX_RATIO 0xa8 /* double byte command */
|
||||
|
||||
#define SSD1306_SET_COM_OUTPUT_SCAN_NORMAL 0xc0
|
||||
#define SSD1306_SET_COM_OUTPUT_SCAN_FLIPPED 0xc8
|
||||
|
||||
#define SSD1306_SET_DISPLAY_OFFSET 0xd3 /* double byte command */
|
||||
|
||||
#define SSD1306_SET_PADS_HW_CONFIG 0xda /* double byte command */
|
||||
#define SSD1306_SET_PADS_HW_SEQUENTIAL 0x02
|
||||
#define SSD1306_SET_PADS_HW_ALTERNATIVE 0x12
|
||||
|
||||
|
||||
/*
|
||||
* Timming and Driving Scheme Setting Command Table
|
||||
*/
|
||||
#define SSD1306_SET_CLOCK_DIV_RATIO 0xd5 /* double byte command */
|
||||
|
||||
#define SSD1306_SET_CHARGE_PERIOD 0xd9 /* double byte command */
|
||||
|
||||
#define SSD1306_SET_VCOM_DESELECT_LEVEL 0xdb /* double byte command */
|
||||
|
||||
#define SSD1306_NOP 0xe3
|
||||
|
||||
/*
|
||||
* Charge Pump Command Table
|
||||
*/
|
||||
#define SSD1306_SET_CHARGE_PUMP_ON 0x8d /* double byte command */
|
||||
#define SSD1306_SET_CHARGE_PUMP_ON_DISABLED 0x10
|
||||
#define SSD1306_SET_CHARGE_PUMP_ON_ENABLED 0x14
|
||||
|
||||
#define SH1106_SET_DCDC_MODE 0xad /* double byte command */
|
||||
#define SH1106_SET_DCDC_DISABLED 0x8a
|
||||
#define SH1106_SET_DCDC_ENABLED 0x8b
|
||||
|
||||
#define SSD1306_SET_PUMP_VOLTAGE_64 0x30
|
||||
#define SSD1306_SET_PUMP_VOLTAGE_74 0x31
|
||||
#define SSD1306_SET_PUMP_VOLTAGE_80 0x32
|
||||
#define SSD1306_SET_PUMP_VOLTAGE_90 0x33
|
||||
|
||||
/*
|
||||
* Read modify write
|
||||
*/
|
||||
#define SSD1306_READ_MODIFY_WRITE_START 0xe0
|
||||
#define SSD1306_READ_MODIFY_WRITE_END 0xee
|
||||
|
||||
#endif
|
68
dts/bindings/display/solomon,ssd1306fb-i2c.yaml
Normal file
68
dts/bindings/display/solomon,ssd1306fb-i2c.yaml
Normal file
|
@ -0,0 +1,68 @@
|
|||
#
|
||||
# Copyright (c) 2018, Phytec Messtechnik GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
---
|
||||
title: SSD1306 128x64 Dot Matrix Display Controller
|
||||
id: solomon,ssd1306fb-i2c
|
||||
version: 0.1
|
||||
|
||||
description: >
|
||||
This is a representation of the SSD1306 128x64 Dot Matrix Display Controller
|
||||
|
||||
inherits:
|
||||
!include i2c-device.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
constraint: "solomon,ssd1306fb-i2c"
|
||||
|
||||
height:
|
||||
type: int
|
||||
category: required
|
||||
generation: Height in pixel of the panel driven by the controller
|
||||
|
||||
width:
|
||||
type: int
|
||||
category: required
|
||||
generation: Width in pixel of the panel driven by the controller
|
||||
|
||||
segment-offset:
|
||||
type: int
|
||||
category: required
|
||||
generation: 8-bit column start address for Page Addressing Mode
|
||||
|
||||
page-offset:
|
||||
type: int
|
||||
category: required
|
||||
generation: Start address for Page Addressing Mode
|
||||
|
||||
display-offset:
|
||||
type: int
|
||||
category: required
|
||||
generation: mapping of the display start line to one of COM0 .. COM63
|
||||
|
||||
segment-remap:
|
||||
type: string
|
||||
category: optional
|
||||
generation: Last column address is mapped to first segment
|
||||
|
||||
com-invdir:
|
||||
type: string
|
||||
category: optional
|
||||
generation: Scan direction is from last COM output to first COM output
|
||||
|
||||
prechargep:
|
||||
type: int
|
||||
category: required
|
||||
generation: Duration of the pre-charge period
|
||||
|
||||
reset-gpios:
|
||||
type: compound
|
||||
category: optional
|
||||
generation: define, use-prop-name
|
||||
|
||||
base_label: SSD1306
|
||||
|
||||
...
|
Loading…
Add table
Add a link
Reference in a new issue