/**************************************************************************** * drivers/lcd/ssd1306.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ #ifndef __DRIVERS_LCD_SSD1306_H #define __DRIVERS_LCD_SSD1306_H /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* Configuration ************************************************************/ /* Limitations of the current configuration that I hope to fix someday */ #if !defined(CONFIG_LCD_SH1106_OLED_132) && \ !defined(CONFIG_LCD_UG2864HSWEG01) && \ !defined(CONFIG_LCD_UG2832HSWEG04) && \ !defined(CONFIG_LCD_DD12864WO4A) && \ !defined(CONFIG_LCD_HILETGO) && \ !defined(CONFIG_LCD_SSD1306_CUSTOM) # error "Unknown and unsupported SSD1306 LCD" #endif #if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) # warning "No support for portrait modes" # undef CONFIG_LCD_LANDSCAPE # define CONFIG_LCD_LANDSCAPE 1 # undef CONFIG_LCD_PORTRAIT # undef CONFIG_LCD_RLANDSCAPE # undef CONFIG_LCD_RPORTRAIT #endif /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #ifndef CONFIG_NX_BGCOLOR # define CONFIG_NX_BGCOLOR SSD1306_Y1_BLACK #endif /* SSD1306 Commands *********************************************************/ #define SSD1306_SETCOLL(ad) (0x00 | ((ad) & 0x0f)) /* Set Lower Column Address: (00h - 0fh) */ #define SSD1306_SETCOLH(ad) (0x10 | ((ad) & 0x0f)) /* Set Higher Column Address: (10h - 1fh) */ #define SSD1306_STARTLINE(ln) (0x40 | ((ln) & 0x3f)) /* Set Display Start Line: (40h - 7fh) */ #define SSD1306_CONTRAST_MODE (0x81) /* Set Contrast Control Register: (Double Bytes Command) */ # define SSD1306_CONTRAST(c) (c) #define SSD1306_SEGREMAP(m) (0xa0 | ((m) & 0x01)) /* Set Segment Re-map: (a0h - a1h) */ # define SSD1306_REMAPRIGHT SSD1306_SEGREMAP(0) /* Right rotation */ # define SSD1306_REMAPPLEFT SSD1306_SEGREMAP(1) /* Left rotation */ #define SSD1306_EDISPOFFON(s) (0xa4 | ((s) & 0x01)) /* Set Entire Display OFF/ON: (a4h - a5h) */ # define SSD1306_EDISPOFF SSD1306_EDISPOFFON(0) /* Display off */ # define SSD1306_EDISPON SSD1306_EDISPOFFON(1) /* Display on */ #define SSD1306_NORMREV(s) (0xa6 | ((s) & 0x01)) /* Set Normal/Reverse Display: (a6h -a7h) */ # define SSD1306_NORMAL SSD1306_NORMREV(0) /* Normal display */ # define SSD1306_REVERSE SSD1306_NORMREV(1) /* Reverse display */ #define SSD1306_MRATIO_MODE (0xa8) /* Set Multiplex Ration: (Double Bytes Command) */ # define SSD1306_MRATIO(d) ((d) & 0x3f) #define SSD1306_DCDC_MODE (0xad) /* Set DC-DC OFF/ON: (Double Bytes Command) */ # define SSD1306_DCDC_OFF (0x8a) # define SSD1306_DCDC_ON (0x8b) #define SSD1306_DISPOFFON(s) (0xae | ((s) & 0x01)) /* Display OFF/ON: (aeh - afh) */ # define SSD1306_DISPOFF SSD1306_DISPOFFON(0) /* Display off */ # define SSD1306_DISPON SSD1306_DISPOFFON(1) /* Display on */ #define SSD1306_PAGEADDR(a) (0xb0 | ((a) & 0x0f)) /* Set Page Address: (b0h - b7h) */ #define SSD1306_SCANDIR(d) (0xc0 | ((d) & 0x08)) /* Set Common Output Scan Direction: (c0h - c8h) */ # define SSD1306_SCANFROMCOM0 SSD1306_SCANDIR(0x00) /* Scan from COM[0] to COM[n-1]*/ # define SSD1306_SCANTOCOM0 SSD1306_SCANDIR(0x08) /* Scan from COM[n-1] to COM[0] */ #define SSD1306_DISPOFFS_MODE (0xd3) /* Set Display Offset: (Double Bytes Command) */ # define SSD1306_DISPOFFS(o) ((o) & 0x3f) #define SSD1306_CLKDIV_SET (0xd5) /* Set Display Clock Divide Ratio/Oscillator Frequency: (Double Bytes Command) */ # define SSD1306_CLKDIV(f,d) ((((f) & 0x0f) << 4) | ((d) & 0x0f)) #define SSD1306_CHRGPER_SET (0xd9) /* Set Dis-charge/Pre-charge Period: (Double Bytes Command) */ # define SSD1306_CHRGPER(d,p) ((((d) & 0x0f) << 4) | ((p) & 0x0f)) #define SSD1306_CMNPAD_CONFIG (0xda) /* Set Common pads hardware configuration: (Double Bytes Command) */ # define SSD1306_CMNPAD(c) ((0x02) | ((c) & 0x10)) #define SSD1306_VCOM_SET (0xdb) /* Set VCOM Deselect Level: (Double Byte Command) */ # define SSD1306_VCOM(v) (v) #define SSD1306_CHRPUMP_SET (0x8d) /* Charge Pump Setting */ # define SSD1306_CHRPUMP_ON (0x14) # define SSD1306_CHRPUMP_OFF (0x10) #define SSD1306_RMWSTART (0xe0) /* Read-Modify-Write: (e0h) */ #define SSD1306_NOP (0xe3) /* NOP: (e3h) */ #define SSD1306_END (0xee) /* End: (eeh) */ #define SSD1306_WRDATA(d) (d) /* Write Display Data */ #define SSD1306_STATUS_BUSY (0x80) /* Read Status */ #define SSD1306_STATUS_ONOFF (0x40) #define SSD1306_RDDATA(d) (d) /* Read Display Data */ #define SSD1309_PROTOFF (0xfd) #define SSD1309_SETMEMORY (0x20) # define SSD1309_MEMADDR(ma) ((ma) & 0x03) /* Color Properties *********************************************************/ /* Display Resolution * * The SSD1306 display controller can handle a resolution of 132x64. * The UG-2864HSWEG01 on the base board is 128x64; the UG-2832HSWEG04 * is 128x32. */ #if defined(CONFIG_LCD_UG2864HSWEG01) # define SSD1306_DEV_NATIVE_XRES 128 /* Only 128 of 131 columns used */ # define SSD1306_DEV_NATIVE_YRES 64 /* 8 pages each 8 rows */ # define SSD1306_DEV_XOFFSET 2 /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES 8 /* 8 pages */ # define SSD1306_DEV_CMNPAD 0x12 /* COM configuration */ # undef IS_SSD1309 #elif defined(CONFIG_LCD_UG2832HSWEG04) # define SSD1306_DEV_NATIVE_XRES 128 /* Only 128 of 131 columns used */ # define SSD1306_DEV_NATIVE_YRES 32 /* 4 pages each 8 rows */ # define SSD1306_DEV_XOFFSET 2 /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES 4 /* 4 pages */ # define SSD1306_DEV_CMNPAD 0x02 /* COM configuration */ # undef IS_SSD1309 #elif defined(CONFIG_LCD_SH1106_OLED_132) # define SSD1306_DEV_NATIVE_XRES 128 /* Only 128 columns used, supporting 132 is a bit difficult */ # define SSD1306_DEV_NATIVE_YRES 64 /* 8 pages each 8 rows */ # define SSD1306_DEV_XOFFSET 0 /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES 8 /* 8 pages */ # define SSD1306_DEV_CMNPAD 0x12 /* COM configuration */ # undef IS_SSD1309 #elif defined(CONFIG_LCD_HILETGO) # define SSD1306_DEV_NATIVE_XRES 128 /* Only 128 of 132 columns supported */ # define SSD1306_DEV_NATIVE_YRES 64 /* 8 pages each 8 rows */ # define SSD1306_DEV_XOFFSET 0 /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES 8 /* 8 pages */ # define SSD1306_DEV_CMNPAD 0x12 /* COM configuration */ # undef IS_SSD1309 #elif defined(CONFIG_LCD_DD12864WO4A) # define SSD1306_DEV_NATIVE_XRES 128 /* 128 of 128 columns used */ # define SSD1306_DEV_NATIVE_YRES 64 /* 8 pages each 8 rows */ # define SSD1306_DEV_XOFFSET 0 /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES 8 /* 8 pages */ # define SSD1306_DEV_CMNPAD 0x10 /* COM configuration */ # define IS_SSD1309 1 /* SSD1309 based LCD. */ #elif defined(CONFIG_LCD_SSD1306_CUSTOM) # define SSD1306_DEV_NATIVE_XRES CONFIG_LCD_SSD1306_CUSTOM_DEV_NATIVE_XRES /* Only 128 of 131 columns used */ # define SSD1306_DEV_NATIVE_YRES CONFIG_LCD_SSD1306_CUSTOM_DEV_NATIVE_YRES /* 4 pages each 8 rows */ # define SSD1306_DEV_XOFFSET CONFIG_LCD_SSD1306_CUSTOM_DEV_XOFFSET /* Offset to logical column 0 */ # define SSD1306_DEV_PAGES CONFIG_LCD_SSD1306_CUSTOM_DEV_PAGES /* 4 pages */ # define SSD1306_DEV_CMNPAD CONFIG_LCD_SSD1306_CUSTOM_DEV_CMNPAD /* COM configuration */ # undef IS_SSD1309 #endif #if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) # define SSD1306_DEV_XRES SSD1306_DEV_NATIVE_XRES # define SSD1306_DEV_YRES SSD1306_DEV_NATIVE_YRES #else # define SSD1306_DEV_XRES SSD1306_DEV_NATIVE_YRES # define SSD1306_DEV_YRES SSD1306_DEV_NATIVE_XRES #endif #define SSD1306_DEV_DUTY (SSD1306_DEV_NATIVE_YRES-1) /* Bytes per logical row and actual device row */ #if defined(CONFIG_LCD_SH1106_OLED_132) # define SSD1306_DEV_XSTRIDE (SSD1306_DEV_XRES >> 3) #else # define SSD1306_DEV_XSTRIDE (SSD1306_DEV_XRES >> 3) #endif #define SSD1306_DEV_YSTRIDE (SSD1306_DEV_YRES >> 3) /* Color depth and format */ #define SSD1306_DEV_BPP 1 #define SSD1306_DEV_COLORFMT FB_FMT_Y1 /* Default contrast */ #define SSD1306_DEV_CONTRAST (128) #define SSD1309_DEV_CONTRAST (255) /* The size of the shadow frame buffer or one row buffer. * * Frame buffer size: 128 columns x 64 rows / 8 bits-per-pixel * Row size: 128 columns x 8 rows-per-page / 8 bits-per-pixel */ #define SSD1306_DEV_FBSIZE (SSD1306_DEV_XSTRIDE * SSD1306_DEV_YRES) #define SSD1306_DEV_ROWSIZE (SSD1306_DEV_XSTRIDE) /* Orientation. There seem to be device differences. */ #if defined(CONFIG_LCD_UG2864HSWEG01) # if defined(CONFIG_LCD_LANDSCAPE) # undef SSD1306_DEV_REVERSEX # undef SSD1306_DEV_REVERSEY # elif defined(CONFIG_LCD_RLANDSCAPE) # define SSD1306_DEV_REVERSEX 1 # define SSD1306_DEV_REVERSEY 1 # endif #elif defined(CONFIG_LCD_UG2832HSWEG04) # if defined(CONFIG_LCD_LANDSCAPE) # define SSD1306_DEV_REVERSEX 1 # undef SSD1306_DEV_REVERSEY # elif defined(CONFIG_LCD_RLANDSCAPE) # undef SSD1306_DEV_REVERSEX # define SSD1306_DEV_REVERSEY 1 # endif #elif defined(CONFIG_LCD_SH1106_OLED_132) # if defined(CONFIG_LCD_LANDSCAPE) # undef SSD1306_DEV_REVERSEX # define SSD1306_DEV_REVERSEY 1 # elif defined(CONFIG_LCD_RLANDSCAPE) # define SSD1306_DEV_REVERSEX 1 # undef SSD1306_DEV_REVERSEY # endif #elif defined(CONFIG_LCD_DD12864WO4A) # if defined(CONFIG_LCD_LANDSCAPE) # define SSD1306_DEV_REVERSEX 1 # undef SSD1306_DEV_REVERSEY # elif defined(CONFIG_LCD_RLANDSCAPE) # undef SSD1306_DEV_REVERSEX # define SSD1306_DEV_REVERSEY 1 # endif #elif defined(CONFIG_LCD_SSD1306_CUSTOM) # if defined(CONFIG_LCD_LANDSCAPE) # define SSD1306_DEV_REVERSEX 1 # undef SSD1306_DEV_REVERSEY # elif defined(CONFIG_LCD_RLANDSCAPE) # undef SSD1306_DEV_REVERSEX # define SSD1306_DEV_REVERSEY 1 # endif #endif /* Bit helpers */ #define LS_BIT (1 << 0) #define MS_BIT (1 << 7) /**************************************************************************** * Public Type Definition ****************************************************************************/ /* This structure describes the state of the SSD1306 driver */ struct ssd1306_dev_s { struct lcd_dev_s dev; /* Publicly visible device structure */ /* Private LCD-specific information follows */ #ifdef CONFIG_LCD_SSD1306_SPI FAR struct spi_dev_s *spi; /* Cached SPI device reference */ #else FAR struct i2c_master_s *i2c; /* Cached I2C device reference */ uint8_t addr; /* 7-bit I2C address */ #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 a shadow copy of the framebuffer memory. At 128x64, this * amounts to 1 KB. */ uint8_t fb[SSD1306_DEV_FBSIZE]; }; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ 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); void ssd1306_cmddata(FAR struct ssd1306_dev_s *priv, bool cmd); void ssd1306_configspi(FAR struct spi_dev_s *spi); #else # define ssd1306_select(priv, cs) # define ssd1306_cmddata(priv, cmd) # define ssd1306_configspi(spi) #endif #endif /* __DRIVERS_LCD_SSD1306_H */