SH1107: Add driver and example.

Add 1bit pen mode to PicoGraphics.

TODO:

* Rotation support
* Sizes other than 128x128 support
experimental/8bitfb-pixelspan
jon 2022-06-15 16:37:27 +01:00 zatwierdzone przez Phil Howard
rodzic 48b9e5a96e
commit 360bf4310c
13 zmienionych plików z 417 dodań i 90 usunięć

Wyświetl plik

@ -1,37 +1,39 @@
add_subdirectory(analog)
add_subdirectory(analogmux)
add_subdirectory(esp32spi)
add_subdirectory(ioexpander)
add_subdirectory(ltp305)
add_subdirectory(ltr559)
add_subdirectory(pmw3901)
add_subdirectory(sgp30)
add_subdirectory(st7735)
add_subdirectory(st7789)
add_subdirectory(msa301)
add_subdirectory(rv3028)
add_subdirectory(trackball)
add_subdirectory(vl53l1x)
add_subdirectory(is31fl3731)
add_subdirectory(fatfs)
add_subdirectory(sdcard)
add_subdirectory(as7262)
add_subdirectory(bh1745)
add_subdirectory(bme68x)
add_subdirectory(bmp280)
add_subdirectory(bme280)
add_subdirectory(button)
add_subdirectory(pid)
add_subdirectory(plasma)
add_subdirectory(rgbled)
add_subdirectory(icp10125)
add_subdirectory(scd4x)
add_subdirectory(hub75)
add_subdirectory(uc8151)
add_subdirectory(pwm)
add_subdirectory(servo)
add_subdirectory(encoder)
add_subdirectory(motor)
add_subdirectory(vl53l5cx)
add_subdirectory(pcf85063a)
add_subdirectory(pms5003)
add_subdirectory(analog)
add_subdirectory(analogmux)
add_subdirectory(esp32spi)
add_subdirectory(ioexpander)
add_subdirectory(ltp305)
add_subdirectory(ltr559)
add_subdirectory(pmw3901)
add_subdirectory(sgp30)
add_subdirectory(st7735)
add_subdirectory(st7789)
add_subdirectory(msa301)
add_subdirectory(rv3028)
add_subdirectory(trackball)
add_subdirectory(vl53l1x)
add_subdirectory(is31fl3731)
add_subdirectory(fatfs)
add_subdirectory(sdcard)
add_subdirectory(as7262)
add_subdirectory(bh1745)
add_subdirectory(bme68x)
add_subdirectory(bmp280)
add_subdirectory(bme280)
add_subdirectory(button)
add_subdirectory(pid)
add_subdirectory(plasma)
add_subdirectory(rgbled)
add_subdirectory(icp10125)
add_subdirectory(scd4x)
add_subdirectory(hub75)
add_subdirectory(uc8151)
add_subdirectory(pwm)
add_subdirectory(servo)
add_subdirectory(encoder)
add_subdirectory(motor)
add_subdirectory(vl53l5cx)
add_subdirectory(pcf85063a)
add_subdirectory(pms5003)
add_subdirectory(sh1107)

Wyświetl plik

@ -0,0 +1 @@
include(${CMAKE_CURRENT_LIST_DIR}/sh1107.cmake)

Wyświetl plik

@ -0,0 +1,58 @@
# ST7789 Display Driver for Pimoroni LCDs <!-- omit in toc -->
The ST7789 driver supports both Parallel and Serial (SPI) ST7789 displays and is intended for use with:
* Pico Display
* Pico Display 2.0
* Tufty 2040
* Pico Explorer
* 240x240 Round & Square SPI LCD Breakouts
## Setup
Construct an instance of the ST7789 driver with either Parallel or SPI pins.
Parallel:
```c++
ST7789 st7789(WIDTH, HEIGHT, ROTATE_0, {
Tufty2040::LCD_CS, // Chip-Select
Tufty2040::LCD_DC, // Data-Command
Tufty2040::LCD_WR, // Write
Tufty2040::LCD_RD, // Read
Tufty2040::LCD_D0, // Data 0 (start of a bank of 8 pins)
Tufty2040::BACKLIGHT // Backlight
});
```
SPI:
```c++
ST7789 st7789(WIDTH, HEIGHT, ROTATE_0, false, {
PIMORONI_SPI_DEFAULT_INSTANCE, // SPI instance
SPI_BG_FRONT_CS, // Chip-select
SPI_DEFAULT_SCK, // SPI Clock
SPI_DEFAULT_MOSI, // SPI Out
PIN_UNUSED, // SPI In
SPI_DEFAULT_DC, // SPI Data/Command
PIN_UNUSED // Backlight
});
```
## Reference
### Update
ST7789's `update` accepts an instance of `PicoGraphics` in any colour mode:
```c++
st7789.update(&graphics);
```
### Set Backlight
If a backlight pin has been configured, you can set the backlight from 0 to 255:
```c++
st7789.set_backlight(128)
```

Wyświetl plik

@ -0,0 +1,12 @@
set(DRIVER_NAME sh1107)
add_library(${DRIVER_NAME} INTERFACE)
target_sources(${DRIVER_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(sh1107 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib pimoroni_i2c pico_graphics)

Wyświetl plik

@ -0,0 +1,49 @@
#include "sh1107.hpp"
#include <cstdlib>
#include <math.h>
#include <string.h>
namespace pimoroni {
void SH1107::update(PicoGraphics *graphics) {
if(graphics->pen_type == PicoGraphics::PEN_1BIT) { // Display buffer is screen native
uint8_t *p = (uint8_t *)graphics->frame_buffer;
uint framebuffer_size = PicoGraphics_Pen1Bit::buffer_size(width, height);
uint page_size = framebuffer_size / 16;
uint8_t temp[framebuffer_size] = {0};
uint8_t *ptemp = temp;
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint bo = 7 - (x & 0b111);
uint8_t color = p[(x / 8) + (y * width / 8)] & (1U << bo);
if(color) {
temp[x + (y / 8 ) * width] |= 1 << (y % 8);
}else{
temp[x + (y / 8 ) * width] &= ~(1 << (y % 8));
}
}
}
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);
memcpy(buf + 1, ptemp, page_size);
buf[0] = 0x40;
i2c.write_blocking(0x3c, buf, page_size + 1, false);
ptemp += page_size;
}
}
}
}

Wyświetl plik

@ -0,0 +1,85 @@
#pragma once
#include "hardware/i2c.h"
#include "hardware/gpio.h"
#include "common/pimoroni_common.hpp"
#include "common/pimoroni_i2c.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include <algorithm>
namespace pimoroni {
class SH1107 : public DisplayDriver {
I2C &i2c;
public:
bool round;
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
public:
// Parallel init
SH1107(uint16_t width, uint16_t height, I2C &i2c) :
DisplayDriver(width, height, ROTATE_0),
i2c(i2c) {
i2c.reg_write_uint8(0x3c, 0, 0xae);
i2c.reg_write_uint8(0x3c, 0, 0x20); // set memory addressing mode
i2c.reg_write_uint8(0x3c, 0, 0x00);
i2c.reg_write_uint8(0x3c, 0, 0xb0); // set page start address
i2c.reg_write_uint8(0x3c, 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(0x3c, 0, 0x40);
i2c.reg_write_uint8(0x3c, 0, 0xa0); // mirror horizontally
i2c.reg_write_uint8(0x3c, 0, 0xa6); // no inversion
i2c.reg_write_uint8(0x3c, 0, 0xff); // ??????!
i2c.reg_write_uint8(0x3c, 0, 0x3f); // confusion intensifies..
i2c.reg_write_uint8(0x3c, 0, 0xa4);
i2c.reg_write_uint8(0x3c, 0, 0xd3); // set display offset
i2c.reg_write_uint8(0x3c, 0, 0x00);
i2c.reg_write_uint8(0x3c, 0, 0xd5); // set display clock divide
i2c.reg_write_uint8(0x3c, 0, 0xf0);
i2c.reg_write_uint8(0x3c, 0, 0xd9); // set precharge period
i2c.reg_write_uint8(0x3c, 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(0x3c, 0, 0xdb); // set vcomh
i2c.reg_write_uint8(0x3c, 0, 0x20);
i2c.reg_write_uint8(0x3c, 0, 0x8d); // set dc-dc enable
i2c.reg_write_uint8(0x3c, 0, 0x14);
i2c.reg_write_uint8(0x3c, 0, 0xaf); // turn display on
}
void update(PicoGraphics *graphics) override;
private:
void common_init();
void command(uint8_t command, size_t len = 0, const char *data = NULL);
};
}

Wyświetl plik

@ -1,51 +1,52 @@
add_subdirectory(breakout_dotmatrix)
add_subdirectory(breakout_encoder)
add_subdirectory(breakout_ioexpander)
add_subdirectory(breakout_ltr559)
add_subdirectory(breakout_colourlcd160x80)
add_subdirectory(breakout_roundlcd)
add_subdirectory(breakout_rgbmatrix5x5)
add_subdirectory(breakout_matrix11x7)
add_subdirectory(breakout_mics6814)
add_subdirectory(breakout_pmw3901)
add_subdirectory(breakout_potentiometer)
add_subdirectory(breakout_rtc)
add_subdirectory(breakout_trackball)
add_subdirectory(breakout_sgp30)
add_subdirectory(breakout_colourlcd240x240)
add_subdirectory(breakout_msa301)
add_subdirectory(breakout_bme688)
add_subdirectory(breakout_bmp280)
add_subdirectory(breakout_bme280)
add_subdirectory(breakout_as7262)
add_subdirectory(breakout_bh1745)
add_subdirectory(breakout_icp10125)
add_subdirectory(breakout_scd41)
add_subdirectory(breakout_vl53l5cx)
add_subdirectory(breakout_pms5003)
add_subdirectory(pico_display)
add_subdirectory(pico_display_2)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_unicorn_plasma)
add_subdirectory(pico_scroll)
add_subdirectory(pico_enc_explorer)
add_subdirectory(pico_explorer)
add_subdirectory(pico_pot_explorer)
add_subdirectory(pico_explorer_encoder)
add_subdirectory(pico_motor_shim)
add_subdirectory(pico_rgb_keypad)
add_subdirectory(pico_rtc_display)
add_subdirectory(pico_rtc)
add_subdirectory(pico_tof_display)
add_subdirectory(pico_trackball_display)
add_subdirectory(pico_audio)
add_subdirectory(pico_wireless)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(tufty2040)
add_subdirectory(interstate75)
add_subdirectory(servo2040)
add_subdirectory(motor2040)
add_subdirectory(encoder)
add_subdirectory(breakout_dotmatrix)
add_subdirectory(breakout_encoder)
add_subdirectory(breakout_ioexpander)
add_subdirectory(breakout_ltr559)
add_subdirectory(breakout_colourlcd160x80)
add_subdirectory(breakout_roundlcd)
add_subdirectory(breakout_rgbmatrix5x5)
add_subdirectory(breakout_matrix11x7)
add_subdirectory(breakout_mics6814)
add_subdirectory(breakout_pmw3901)
add_subdirectory(breakout_potentiometer)
add_subdirectory(breakout_rtc)
add_subdirectory(breakout_trackball)
add_subdirectory(breakout_sgp30)
add_subdirectory(breakout_colourlcd240x240)
add_subdirectory(breakout_msa301)
add_subdirectory(breakout_bme688)
add_subdirectory(breakout_bmp280)
add_subdirectory(breakout_bme280)
add_subdirectory(breakout_as7262)
add_subdirectory(breakout_bh1745)
add_subdirectory(breakout_icp10125)
add_subdirectory(breakout_scd41)
add_subdirectory(breakout_vl53l5cx)
add_subdirectory(breakout_pms5003)
add_subdirectory(breakout_oled_128x128)
add_subdirectory(pico_display)
add_subdirectory(pico_display_2)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_unicorn_plasma)
add_subdirectory(pico_scroll)
add_subdirectory(pico_enc_explorer)
add_subdirectory(pico_explorer)
add_subdirectory(pico_pot_explorer)
add_subdirectory(pico_explorer_encoder)
add_subdirectory(pico_motor_shim)
add_subdirectory(pico_rgb_keypad)
add_subdirectory(pico_rtc_display)
add_subdirectory(pico_rtc)
add_subdirectory(pico_tof_display)
add_subdirectory(pico_trackball_display)
add_subdirectory(pico_audio)
add_subdirectory(pico_wireless)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(tufty2040)
add_subdirectory(interstate75)
add_subdirectory(servo2040)
add_subdirectory(motor2040)
add_subdirectory(encoder)

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME oled_128x128_demo)
add_executable(
${OUTPUT_NAME}
oled_128x128_demo.cpp
)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib pico_graphics sh1107)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,52 @@
#include <string.h>
#include <math.h>
#include <vector>
#include <cstdlib>
#include "drivers/sh1107/sh1107.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "time.h"
using namespace pimoroni;
const int WIDTH = 128;
const int HEIGHT = 128;
I2C i2c(4, 5);
SH1107 sh1107(WIDTH, HEIGHT, i2c);
PicoGraphics_Pen1Bit graphics(sh1107.width, sh1107.height, nullptr);
int main() {
uint i = 0;
while(true) {
// for(int y = 0; y < 128; y++) {
// for(int x = 0; x < 128; x++) {
// graphics.set_pen(((x + y + i) & 0b1111) > 8 ? 1 : 0);
// graphics.set_pixel({x, y});
// }
// }
graphics.set_pen(1);
graphics.clear();
float s = (sin(i / 10.0f) * 1.0f) + 1.5f;
float a = (cos(i / 10.0f) * 10.0f);
graphics.set_font("gothic");
graphics.set_pen(0);
int w = graphics.measure_text("PIRATES!", s);
graphics.text("PIRATES!", {64 - w / 2, 60}, 0, s, a);
sh1107.update(&graphics);
//sleep_ms(10);
i++;
}
}

Wyświetl plik

@ -1,6 +1,7 @@
add_library(pico_graphics
${CMAKE_CURRENT_LIST_DIR}/types.cpp
${CMAKE_CURRENT_LIST_DIR}/pico_graphics.cpp
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_1bit.cpp
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p4.cpp
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p8.cpp
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_rgb332.cpp

Wyświetl plik

@ -128,7 +128,8 @@ namespace pimoroni {
class PicoGraphics {
public:
enum PenType {
PEN_P2 = 0,
PEN_1BIT,
PEN_P2,
PEN_P4,
PEN_P8,
PEN_RGB332,
@ -221,6 +222,21 @@ namespace pimoroni {
void line(Point p1, Point p2);
};
class PicoGraphics_Pen1Bit : public PicoGraphics {
public:
uint8_t color;
PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
void set_pixel(const Point &p) override;
static size_t buffer_size(uint w, uint h) {
return w * h / 8;
}
};
class PicoGraphics_PenP4 : public PicoGraphics {
public:

Wyświetl plik

@ -0,0 +1,35 @@
#include "pico_graphics.hpp"
namespace pimoroni {
PicoGraphics_Pen1Bit::PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer)
: PicoGraphics(width, height, frame_buffer) {
this->pen_type = PEN_1BIT;
if(this->frame_buffer == nullptr) {
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
}
}
void PicoGraphics_Pen1Bit::set_pen(uint c) {
color = c != 0 ? 1 : 0;
}
void PicoGraphics_Pen1Bit::set_pen(uint8_t r, uint8_t g, uint8_t b) {
color = r != 0 || g != 0 || b != 0 ? 1 : 0;
}
void PicoGraphics_Pen1Bit::set_pixel(const Point &p) {
// pointer to byte in framebuffer that contains this pixel
uint8_t *buf = (uint8_t *)frame_buffer;
uint8_t *f = &buf[(p.x / 8) + (p.y * bounds.w / 8)];
uint bo = 7 - (p.x & 0b111);
// forceably clear the bit
*f &= ~(1U << bo);
// set pixel
*f |= (color << bo);
}
}

Wyświetl plik

@ -107,6 +107,9 @@ static int _open(_JPEG_obj_t *self) {
case PicoGraphics::PEN_P2:
self->jpeg->setPixelType(TWO_BIT_DITHERED);
break;
case PicoGraphics::PEN_1BIT:
self->jpeg->setPixelType(ONE_BIT_DITHERED);
break;
}
}
return result;
@ -192,4 +195,4 @@ mp_obj_t _JPEG_getHeight(mp_obj_t self_in) {
return mp_obj_new_int(self->jpeg->getHeight());
}
}
}