""" Program 12-2: OLED_SSD1306 via I2C This program communicates with the OLED_SSD1306 via I2C. It uses framebuf. Connection: SCL - GP17, SDA - GP16 """ import time import framebuf from machine import I2C, Pin DEV_ADDR = 0x3C SCREEN_WIDTH = 128 SCREEN_HEIGHT = 64 SCREEN_PAGE_NUM = 8 SSD1306_WHITE = 1 SSD1306_BLACK = 0 # Instantiate i2c with SCL - GP17, SDA - GP16 i2c = I2C(0, scl = Pin(17), sda = Pin(16), freq = 400_000) # Instantiate a frame buffer buffer = bytearray(SCREEN_WIDTH * SCREEN_HEIGHT // 8) fbuf = framebuf.FrameBuffer(buffer, SCREEN_WIDTH, SCREEN_HEIGHT, framebuf.MONO_VLSB) def ssd1306_data(data): """Write a byte of data to SSD1306""" i2c.writeto(DEV_ADDR, bytearray([0xC0, data])) def ssd1306_command(cmd): """Write a byte of command to SSD1306""" i2c.writeto(DEV_ADDR, bytearray([0x80, cmd])) def ssd1306_init(): """Initialize SSD1306""" INIT_SEQ = ( 0xae, # turn off oled panel 0x00, # set low column address 0x10, # set high column address 0x40, # set start line address 0x20, 0x02, # page addressing mode 0xc8, # top-down segment (4th quadrant) 0x81, # set contrast control register 0xcf, 0xa1, # set segment re-map 95 to 0 0xa6, # set normal display 0xa8, # set multiplex ratio(1 to 64) 0x3f, # 1/64 duty 0xd3, # set display offset 0x00, # not offset 0xd5, # set display clock divide ratio/oscillator frequency 0x80, # set divide ratio 0xd9, # set pre-charge period 0xf1, 0xda, # set com pins hardware configuration 0x12, 0xdb, # set vcomh 0x40, 0x8d, # set Charge Pump enable/disable 0x14, # set(0x10) disable 0xaf # turn on oled panel ) time.sleep_ms(100) for command in INIT_SEQ: ssd1306_command(command) def ssd1306_setRegion(x0, x1, y): """Set active region to x0, x1, y, y. The maximum region can be set is a page.""" ssd1306_command(0x21) # set column ssd1306_command(x0) # starting column ssd1306_command(x1) # end column ssd1306_command(0x22) # set page ssd1306_command(y) # starting page ssd1306_command(y) # end page def ssd1306_flush(): """Write the buffer to the display one page at a time""" for page in range(SCREEN_PAGE_NUM): ssd1306_setRegion(0, SCREEN_WIDTH - 1, page) for column in range(SCREEN_WIDTH): ssd1306_data(buffer[page * SCREEN_WIDTH + column]) # Initialize the SSD1306 controller ssd1306_init() # Write a message fbuf.fill(SSD1306_BLACK) fbuf.text('Hello from', 0, 5, SSD1306_WHITE) fbuf.text('MicroPython.', 20, 16, SSD1306_WHITE) # Draw nested rectangles x = 10 y = 30 w = SCREEN_WIDTH - 20 h = SCREEN_HEIGHT - 30 c = SSD1306_WHITE while h > 0: fbuf.fill_rect(x, y, w, h, c) x += 2 y += 2 w -= 4 h -= 4 c = SSD1306_WHITE if c == SSD1306_BLACK else SSD1306_BLACK # Write the frame buffer out to the display ssd1306_flush()