Module SSD1306
[hide private]
[frames] | no frames]

Source Code for Module SSD1306

  1  # Copyright (c) 2014 Adafruit Industries 
  2  # Author: Tony DiCola 
  3  # Slightly modified by AP (www.aplu.ch) to support no reset pin (rst = None) 
  4   
  5  # Permission is hereby granted, free of charge, to any person obtaining a copy 
  6  # of this software and associated documentation files (the "Software"), to deal 
  7  # in the Software without restriction, including without limitation the rights 
  8  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  9  # copies of the Software, and to permit persons to whom the Software is 
 10  # furnished to do so, subject to the following conditions: 
 11  # 
 12  # The above copyright notice and this permission notice shall be included in 
 13  # all copies or substantial portions of the Software. 
 14  # 
 15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 16  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 17  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 18  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 19  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 20  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 21  # THE SOFTWARE. 
 22  from __future__ import division 
 23  import logging 
 24  import time 
 25   
 26  import Adafruit_GPIO as GPIO 
 27  import Adafruit_GPIO.SPI as SPI 
 28   
 29   
 30  # Constants 
 31  SSD1306_I2C_ADDRESS = 0x3C    # 011110+SA0+RW - 0x3C or 0x3D 
 32  SSD1306_SETCONTRAST = 0x81 
 33  SSD1306_DISPLAYALLON_RESUME = 0xA4 
 34  SSD1306_DISPLAYALLON = 0xA5 
 35  SSD1306_NORMALDISPLAY = 0xA6 
 36  SSD1306_INVERTDISPLAY = 0xA7 
 37  SSD1306_DISPLAYOFF = 0xAE 
 38  SSD1306_DISPLAYON = 0xAF 
 39  SSD1306_SETDISPLAYOFFSET = 0xD3 
 40  SSD1306_SETCOMPINS = 0xDA 
 41  SSD1306_SETVCOMDETECT = 0xDB 
 42  SSD1306_SETDISPLAYCLOCKDIV = 0xD5 
 43  SSD1306_SETPRECHARGE = 0xD9 
 44  SSD1306_SETMULTIPLEX = 0xA8 
 45  SSD1306_SETLOWCOLUMN = 0x00 
 46  SSD1306_SETHIGHCOLUMN = 0x10 
 47  SSD1306_SETSTARTLINE = 0x40 
 48  SSD1306_MEMORYMODE = 0x20 
 49  SSD1306_COLUMNADDR = 0x21 
 50  SSD1306_PAGEADDR = 0x22 
 51  SSD1306_COMSCANINC = 0xC0 
 52  SSD1306_COMSCANDEC = 0xC8 
 53  SSD1306_SEGREMAP = 0xA0 
 54  SSD1306_CHARGEPUMP = 0x8D 
 55  SSD1306_EXTERNALVCC = 0x1 
 56  SSD1306_SWITCHCAPVCC = 0x2 
 57   
 58  # Scrolling constants 
 59  SSD1306_ACTIVATE_SCROLL = 0x2F 
 60  SSD1306_DEACTIVATE_SCROLL = 0x2E 
 61  SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 
 62  SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 
 63  SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 
 64  SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 
 65  SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A 
 66   
67 -class SSD1306Base(object):
68 """Base class for SSD1306-based OLED displays. Implementors should subclass 69 and provide an implementation for the _initialize function. 70 """ 71
72 - def __init__(self, width, height, rst, dc=None, sclk=None, din=None, cs=None, 73 gpio=None, spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS, 74 i2c=None):
75 self._log = logging.getLogger('Adafruit_SSD1306.SSD1306Base') 76 self._spi = None 77 self._i2c = None 78 self.width = width 79 self.height = height 80 self._pages = height//8 81 self._buffer = [0]*(width*self._pages) 82 # Default to platform GPIO if not provided. 83 self._gpio = gpio 84 if self._gpio is None: 85 self._gpio = GPIO.get_platform_gpio() 86 # Setup reset pin. 87 self._rst = rst 88 if self._rst != None: # inserted by AP 89 self._gpio.setup(self._rst, GPIO.OUT) 90 # Handle hardware SPI 91 if spi is not None: 92 self._log.debug('Using hardware SPI') 93 self._spi = spi 94 self._spi.set_clock_hz(8000000) 95 # Handle software SPI 96 elif sclk is not None and din is not None and cs is not None: 97 self._log.debug('Using software SPI') 98 self._spi = SPI.BitBang(self._gpio, sclk, din, None, cs) 99 # Handle hardware I2C 100 elif i2c is not None: 101 self._log.debug('Using hardware I2C with custom I2C provider.') 102 self._i2c = i2c.get_i2c_device(i2c_address) 103 else: 104 self._log.debug('Using hardware I2C with platform I2C provider.') 105 import Adafruit_GPIO.I2C as I2C 106 if i2c_bus is None: 107 self._i2c = I2C.get_i2c_device(i2c_address) 108 else: 109 self._i2c = I2C.get_i2c_device(i2c_address, busnum=i2c_bus) 110 # Initialize DC pin if using SPI. 111 if self._spi is not None: 112 if dc is None: 113 raise ValueError('DC pin must be provided when using SPI.') 114 self._dc = dc 115 self._gpio.setup(self._dc, GPIO.OUT)
116
117 - def _initialize(self):
118 raise NotImplementedError
119
120 - def command(self, c):
121 """Send command byte to display.""" 122 if self._spi is not None: 123 # SPI write. 124 self._gpio.set_low(self._dc) 125 self._spi.write([c]) 126 else: 127 # I2C write. 128 control = 0x00 # Co = 0, DC = 0 129 self._i2c.write8(control, c)
130
131 - def data(self, c):
132 """Send byte of data to display.""" 133 if self._spi is not None: 134 # SPI write. 135 self._gpio.set_high(self._dc) 136 self._spi.write([c]) 137 else: 138 # I2C write. 139 control = 0x40 # Co = 0, DC = 0 140 self._i2c.write8(control, c)
141
142 - def begin(self, vccstate=SSD1306_SWITCHCAPVCC):
143 """Initialize display.""" 144 # Save vcc state. 145 self._vccstate = vccstate 146 # Reset and initialize display. 147 self.reset() 148 self._initialize() 149 # Turn on the display. 150 self.command(SSD1306_DISPLAYON)
151
152 - def reset(self):
153 if self._rst == None: # inserted by AP 154 return 155 """Reset the display.""" 156 # Set reset high for a millisecond. 157 self._gpio.set_high(self._rst) 158 time.sleep(0.001) 159 # Set reset low for 10 milliseconds. 160 self._gpio.set_low(self._rst) 161 time.sleep(0.010) 162 # Set reset high again. 163 self._gpio.set_high(self._rst)
164
165 - def display(self):
166 """Write display buffer to physical display.""" 167 self.command(SSD1306_COLUMNADDR) 168 self.command(0) # Column start address. (0 = reset) 169 self.command(self.width-1) # Column end address. 170 self.command(SSD1306_PAGEADDR) 171 self.command(0) # Page start address. (0 = reset) 172 self.command(self._pages-1) # Page end address. 173 # Write buffer data. 174 if self._spi is not None: 175 # Set DC high for data. 176 self._gpio.set_high(self._dc) 177 # Write buffer. 178 self._spi.write(self._buffer) 179 else: 180 for i in range(0, len(self._buffer), 16): 181 control = 0x40 # Co = 0, DC = 0 182 self._i2c.writeList(control, self._buffer[i:i+16])
183
184 - def image(self, image):
185 """Set buffer to value of Python Imaging Library image. The image should 186 be in 1 bit mode and a size equal to the display size. 187 """ 188 if image.mode != '1': 189 raise ValueError('Image must be in mode 1.') 190 imwidth, imheight = image.size 191 if imwidth != self.width or imheight != self.height: 192 raise ValueError('Image must be same dimensions as display ({0}x{1}).' \ 193 .format(self.width, self.height)) 194 # Grab all the pixels from the image, faster than getpixel. 195 pix = image.load() 196 # Iterate through the memory pages 197 index = 0 198 for page in range(self._pages): 199 # Iterate through all x axis columns. 200 for x in range(self.width): 201 # Set the bits for the column of pixels at the current position. 202 bits = 0 203 # Don't use range here as it's a bit slow 204 for bit in [0, 1, 2, 3, 4, 5, 6, 7]: 205 bits = bits << 1 206 bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 207 # Update buffer byte and increment to next byte. 208 self._buffer[index] = bits 209 index += 1
210
211 - def clear(self):
212 """Clear contents of image buffer.""" 213 self._buffer = [0]*(self.width*self._pages)
214
215 - def set_contrast(self, contrast):
216 """Sets the contrast of the display. Contrast should be a value between 217 0 and 255.""" 218 if contrast < 0 or contrast > 255: 219 raise ValueError('Contrast must be a value from 0 to 255 (inclusive).') 220 self.command(SSD1306_SETCONTRAST) 221 self.command(contrast)
222
223 - def dim(self, dim):
224 """Adjusts contrast to dim the display if dim is True, otherwise sets the 225 contrast to normal brightness if dim is False. 226 """ 227 # Assume dim display. 228 contrast = 0 229 # Adjust contrast based on VCC if not dimming. 230 if not dim: 231 if self._vccstate == SSD1306_EXTERNALVCC: 232 contrast = 0x9F 233 else: 234 contrast = 0xCF
235 236
237 -class SSD1306_128_64(SSD1306Base):
238 - def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None, 239 spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS, 240 i2c=None):
241 # Call base class constructor. 242 super(SSD1306_128_64, self).__init__(128, 64, rst, dc, sclk, din, cs, 243 gpio, spi, i2c_bus, i2c_address, i2c)
244
245 - def _initialize(self):
246 # 128x64 pixel specific initialization. 247 self.command(SSD1306_DISPLAYOFF) # 0xAE 248 self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 249 self.command(0x80) # the suggested ratio 0x80 250 self.command(SSD1306_SETMULTIPLEX) # 0xA8 251 self.command(0x3F) 252 self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 253 self.command(0x0) # no offset 254 self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 255 self.command(SSD1306_CHARGEPUMP) # 0x8D 256 if self._vccstate == SSD1306_EXTERNALVCC: 257 self.command(0x10) 258 else: 259 self.command(0x14) 260 self.command(SSD1306_MEMORYMODE) # 0x20 261 self.command(0x00) # 0x0 act like ks0108 262 self.command(SSD1306_SEGREMAP | 0x1) 263 self.command(SSD1306_COMSCANDEC) 264 self.command(SSD1306_SETCOMPINS) # 0xDA 265 self.command(0x12) 266 self.command(SSD1306_SETCONTRAST) # 0x81 267 if self._vccstate == SSD1306_EXTERNALVCC: 268 self.command(0x9F) 269 else: 270 self.command(0xCF) 271 self.command(SSD1306_SETPRECHARGE) # 0xd9 272 if self._vccstate == SSD1306_EXTERNALVCC: 273 self.command(0x22) 274 else: 275 self.command(0xF1) 276 self.command(SSD1306_SETVCOMDETECT) # 0xDB 277 self.command(0x40) 278 self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 279 self.command(SSD1306_NORMALDISPLAY) # 0xA6
280 281
282 -class SSD1306_128_32(SSD1306Base):
283 - def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None, 284 spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS, 285 i2c=None):
286 # Call base class constructor. 287 super(SSD1306_128_32, self).__init__(128, 32, rst, dc, sclk, din, cs, 288 gpio, spi, i2c_bus, i2c_address, i2c)
289
290 - def _initialize(self):
291 # 128x32 pixel specific initialization. 292 self.command(SSD1306_DISPLAYOFF) # 0xAE 293 self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 294 self.command(0x80) # the suggested ratio 0x80 295 self.command(SSD1306_SETMULTIPLEX) # 0xA8 296 self.command(0x1F) 297 self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 298 self.command(0x0) # no offset 299 self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 300 self.command(SSD1306_CHARGEPUMP) # 0x8D 301 if self._vccstate == SSD1306_EXTERNALVCC: 302 self.command(0x10) 303 else: 304 self.command(0x14) 305 self.command(SSD1306_MEMORYMODE) # 0x20 306 self.command(0x00) # 0x0 act like ks0108 307 self.command(SSD1306_SEGREMAP | 0x1) 308 self.command(SSD1306_COMSCANDEC) 309 self.command(SSD1306_SETCOMPINS) # 0xDA 310 self.command(0x02) 311 self.command(SSD1306_SETCONTRAST) # 0x81 312 self.command(0x8F) 313 self.command(SSD1306_SETPRECHARGE) # 0xd9 314 if self._vccstate == SSD1306_EXTERNALVCC: 315 self.command(0x22) 316 else: 317 self.command(0xF1) 318 self.command(SSD1306_SETVCOMDETECT) # 0xDB 319 self.command(0x40) 320 self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 321 self.command(SSD1306_NORMALDISPLAY) # 0xA6
322 323
324 -class SSD1306_96_16(SSD1306Base):
325 - def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None, 326 spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS, 327 i2c=None):
328 # Call base class constructor. 329 super(SSD1306_96_16, self).__init__(96, 16, rst, dc, sclk, din, cs, 330 gpio, spi, i2c_bus, i2c_address, i2c)
331
332 - def _initialize(self):
333 # 128x32 pixel specific initialization. 334 self.command(SSD1306_DISPLAYOFF) # 0xAE 335 self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 336 self.command(0x60) # the suggested ratio 0x60 337 self.command(SSD1306_SETMULTIPLEX) # 0xA8 338 self.command(0x0F) 339 self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 340 self.command(0x0) # no offset 341 self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 342 self.command(SSD1306_CHARGEPUMP) # 0x8D 343 if self._vccstate == SSD1306_EXTERNALVCC: 344 self.command(0x10) 345 else: 346 self.command(0x14) 347 self.command(SSD1306_MEMORYMODE) # 0x20 348 self.command(0x00) # 0x0 act like ks0108 349 self.command(SSD1306_SEGREMAP | 0x1) 350 self.command(SSD1306_COMSCANDEC) 351 self.command(SSD1306_SETCOMPINS) # 0xDA 352 self.command(0x02) 353 self.command(SSD1306_SETCONTRAST) # 0x81 354 self.command(0x8F) 355 self.command(SSD1306_SETPRECHARGE) # 0xd9 356 if self._vccstate == SSD1306_EXTERNALVCC: 357 self.command(0x22) 358 else: 359 self.command(0xF1) 360 self.command(SSD1306_SETVCOMDETECT) # 0xDB 361 self.command(0x40) 362 self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 363 self.command(SSD1306_NORMALDISPLAY) # 0xA6
364