From b0cfb12b204e86a29e382696ef87744b08cc4d34 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 27 Jun 2022 14:03:53 +0100 Subject: [PATCH] SH1107: Support for alternate i2c address. Add `i2c_address` option to MicroPython PicoGraphics. --- drivers/sh1107/sh1107.cpp | 8 +-- drivers/sh1107/sh1107.hpp | 63 ++++++++++--------- .../modules/picographics/picographics.cpp | 12 ++-- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/drivers/sh1107/sh1107.cpp b/drivers/sh1107/sh1107.cpp index 9a72b514..4220ec69 100644 --- a/drivers/sh1107/sh1107.cpp +++ b/drivers/sh1107/sh1107.cpp @@ -31,14 +31,14 @@ namespace pimoroni { uint8_t buf[page_size + 1]; for(int i = 0; i < 16; i++) { - i2c.reg_write_uint8(0x3c, 0, 0xb0 + i); - i2c.reg_write_uint8(0x3c, 0, 0x00); - i2c.reg_write_uint8(0x3c, 0, 0x10); + i2c.reg_write_uint8(i2c_address, 0, 0xb0 + i); + i2c.reg_write_uint8(i2c_address, 0, 0x00); + i2c.reg_write_uint8(i2c_address, 0, 0x10); memcpy(buf + 1, ptemp, page_size); buf[0] = 0x40; - i2c.write_blocking(0x3c, buf, page_size + 1, false); + i2c.write_blocking(i2c_address, buf, page_size + 1, false); ptemp += page_size; } diff --git a/drivers/sh1107/sh1107.hpp b/drivers/sh1107/sh1107.hpp index 864a4631..f902c327 100644 --- a/drivers/sh1107/sh1107.hpp +++ b/drivers/sh1107/sh1107.hpp @@ -18,61 +18,64 @@ namespace pimoroni { public: bool round; + static const uint8_t DEFAULT_I2C_ADDRESS = 0x3c; + static const uint8_t ALTERNATE_I2C_ADDRESS = 0x3d; //-------------------------------------------------- // Variables //-------------------------------------------------- private: + uint8_t i2c_address = DEFAULT_I2C_ADDRESS; public: - // Parallel init - SH1107(uint16_t width, uint16_t height, I2C &i2c) : + SH1107(uint16_t width, uint16_t height, I2C &i2c) : SH1107(width, height, i2c, DEFAULT_I2C_ADDRESS) {}; + + SH1107(uint16_t width, uint16_t height, I2C &i2c, uint8_t i2c_address) : DisplayDriver(width, height, ROTATE_0), - i2c(i2c) { + i2c(i2c), i2c_address(i2c_address) { - - i2c.reg_write_uint8(0x3c, 0, 0xae); + i2c.reg_write_uint8(i2c_address, 0, 0xae); - i2c.reg_write_uint8(0x3c, 0, 0x20); // set memory addressing mode - i2c.reg_write_uint8(0x3c, 0, 0x00); + i2c.reg_write_uint8(i2c_address, 0, 0x20); // set memory addressing mode + i2c.reg_write_uint8(i2c_address, 0, 0x00); - i2c.reg_write_uint8(0x3c, 0, 0xb0); // set page start address + i2c.reg_write_uint8(i2c_address, 0, 0xb0); // set page start address - i2c.reg_write_uint8(0x3c, 0, 0xc0); // mirror vertically (for australian market) + i2c.reg_write_uint8(i2c_address, 0, 0xc0); // mirror vertically (for australian market) - i2c.reg_write_uint8(0x3c, 0, 0x00); - i2c.reg_write_uint8(0x3c, 0, 0x10); + i2c.reg_write_uint8(i2c_address, 0, 0x00); + i2c.reg_write_uint8(i2c_address, 0, 0x10); - i2c.reg_write_uint8(0x3c, 0, 0x40); + i2c.reg_write_uint8(i2c_address, 0, 0x40); - i2c.reg_write_uint8(0x3c, 0, 0xa0); // mirror horizontally + i2c.reg_write_uint8(i2c_address, 0, 0xa0); // mirror horizontally - i2c.reg_write_uint8(0x3c, 0, 0xa6); // no inversion + i2c.reg_write_uint8(i2c_address, 0, 0xa6); // no inversion - i2c.reg_write_uint8(0x3c, 0, 0xff); // ??????! - i2c.reg_write_uint8(0x3c, 0, 0x3f); // confusion intensifies.. + i2c.reg_write_uint8(i2c_address, 0, 0xff); // ??????! + i2c.reg_write_uint8(i2c_address, 0, 0x3f); // confusion intensifies.. - i2c.reg_write_uint8(0x3c, 0, 0xa4); + i2c.reg_write_uint8(i2c_address, 0, 0xa4); - i2c.reg_write_uint8(0x3c, 0, 0xd3); // set display offset - i2c.reg_write_uint8(0x3c, 0, 0x00); + i2c.reg_write_uint8(i2c_address, 0, 0xd3); // set display offset + i2c.reg_write_uint8(i2c_address, 0, 0x00); - i2c.reg_write_uint8(0x3c, 0, 0xd5); // set display clock divide - i2c.reg_write_uint8(0x3c, 0, 0xf0); + i2c.reg_write_uint8(i2c_address, 0, 0xd5); // set display clock divide + i2c.reg_write_uint8(i2c_address, 0, 0xf0); - i2c.reg_write_uint8(0x3c, 0, 0xd9); // set precharge period - i2c.reg_write_uint8(0x3c, 0, 0x22); + i2c.reg_write_uint8(i2c_address, 0, 0xd9); // set precharge period + i2c.reg_write_uint8(i2c_address, 0, 0x22); - i2c.reg_write_uint8(0x3c, 0, 0xda); // set com pins hardware configuration - i2c.reg_write_uint8(0x3c, 0, 0x12); + i2c.reg_write_uint8(i2c_address, 0, 0xda); // set com pins hardware configuration + i2c.reg_write_uint8(i2c_address, 0, 0x12); - i2c.reg_write_uint8(0x3c, 0, 0xdb); // set vcomh - i2c.reg_write_uint8(0x3c, 0, 0x20); + i2c.reg_write_uint8(i2c_address, 0, 0xdb); // set vcomh + i2c.reg_write_uint8(i2c_address, 0, 0x20); - i2c.reg_write_uint8(0x3c, 0, 0x8d); // set dc-dc enable - i2c.reg_write_uint8(0x3c, 0, 0x14); + i2c.reg_write_uint8(i2c_address, 0, 0x8d); // set dc-dc enable + i2c.reg_write_uint8(i2c_address, 0, 0x14); - i2c.reg_write_uint8(0x3c, 0, 0xaf); // turn display on + i2c.reg_write_uint8(i2c_address, 0, 0xaf); // turn display on } void update(PicoGraphics *graphics) override; diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index 6dca17c8..cc201ee7 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -115,7 +115,7 @@ size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint h mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { ModPicoGraphics_obj_t *self = nullptr; - enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins }; + enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins, ARG_i2c_address }; static const mp_arg_t allowed_args[] = { { MP_QSTR_display, MP_ARG_INT | MP_ARG_REQUIRED }, { MP_QSTR_rotate, MP_ARG_INT, { .u_int = -1 } }, @@ -123,6 +123,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size { MP_QSTR_buffer, MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_pen_type, MP_ARG_INT, { .u_int = -1 } }, { MP_QSTR_extra_pins, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_i2c_address, MP_ARG_INT, { .u_int = -1 } }, }; // Parse args. @@ -174,11 +175,14 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size mp_raise_ValueError("SPIBus expected!"); } } else if (display == DISPLAY_I2C_OLED_128X128) { - if (args[ARG_bus].u_obj == mp_const_none || mp_obj_is_type(args[ARG_bus].u_obj, &PimoroniI2C_type)) { + if (mp_obj_is_type(args[ARG_bus].u_obj, &PimoroniI2C_type)) { _PimoroniI2C_obj_t *i2c = PimoroniI2C_from_machine_i2c_or_native(args[ARG_bus].u_obj); - self->display = m_new_class(SH1107, width, height, *(pimoroni::I2C *)(i2c->i2c)); + + int i2c_address = args[ARG_i2c_address].u_int; + if(i2c_address == -1) i2c_address = SH1107::DEFAULT_I2C_ADDRESS; + self->display = m_new_class(SH1107, width, height, *(pimoroni::I2C *)(i2c->i2c), (uint8_t)i2c_address); } else { - mp_raise_ValueError("I2C bus expected!"); + mp_raise_ValueError("I2C bus required!"); } } else if (display == DISPLAY_INKY_PACK) { if (args[ARG_bus].u_obj == mp_const_none) {