pimoroni-pico/drivers/st7789/st7789.hpp

119 wiersze
3.2 KiB
C++

#pragma once
#include "hardware/spi.h"
#include "hardware/gpio.h"
#include "hardware/pwm.h"
#include "common/pimoroni_common.hpp"
#include "common/pimoroni_bus.hpp"
#include <algorithm>
namespace pimoroni {
class ST7789 {
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
public:
// screen properties
uint16_t width;
uint16_t height;
Rotation rotation;
bool round;
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
// interface pins with our standard defaults where appropriate
uint cs;
uint dc;
uint wr_sck;
uint rd_sck = PIN_UNUSED;
uint d0;
uint bl;
uint vsync = PIN_UNUSED; // only available on some products
// The ST7789 requires 16 ns between SPI rising edges.
// 16 ns = 62,500,000 Hz
static const uint32_t SPI_BAUD = 62'500'000;
public:
// frame buffer where pixel data is stored
void *frame_buffer;
// Parallel init
ST7789(uint16_t width, uint16_t height, Rotation rotation, void *frame_buffer, ParallelPins pins) :
spi(nullptr),
width(width), height(height), rotation(rotation), round(false),
cs(pins.cs), dc(pins.dc), wr_sck(pins.wr_sck), rd_sck(pins.rd_sck), d0(pins.d0), bl(pins.bl), frame_buffer(frame_buffer) {
gpio_set_function(wr_sck, GPIO_FUNC_SIO);
gpio_set_dir(wr_sck, GPIO_OUT);
gpio_set_function(rd_sck, GPIO_FUNC_SIO);
gpio_set_dir(rd_sck, GPIO_OUT);
for(auto i = 0u; i < 8; i++) {
gpio_set_function(d0 + i, GPIO_FUNC_SIO);
gpio_set_dir(d0 + i, GPIO_OUT);
}
gpio_put(rd_sck, 1);
common_init();
}
// Serial init
ST7789(uint16_t width, uint16_t height, Rotation rotation, bool round, void *frame_buffer, SPIPins pins) :
spi(pins.spi),
width(width), height(height), rotation(rotation), round(round),
cs(pins.cs), dc(pins.dc), wr_sck(pins.sck), d0(pins.mosi), bl(pins.bl), frame_buffer(frame_buffer) {
// configure spi interface and pins
spi_init(spi, SPI_BAUD);
gpio_set_function(wr_sck, GPIO_FUNC_SPI);
gpio_set_function(d0, GPIO_FUNC_SPI);
common_init();
}
void init();
void command(uint8_t command, size_t len = 0, const char *data = NULL);
void set_backlight(uint8_t brightness);
void update();
void update(uint16_t *palette);
private:
void configure_display(Rotation rotate);
void write_blocking_parallel(const uint8_t *src, size_t len);
void common_init() {
if(!this->frame_buffer) {
this->frame_buffer = new uint8_t[width * height];
}
gpio_set_function(dc, GPIO_FUNC_SIO);
gpio_set_dir(dc, GPIO_OUT);
gpio_set_function(cs, GPIO_FUNC_SIO);
gpio_set_dir(cs, GPIO_OUT);
// if a backlight pin is provided then set it up for
// pwm control
if(bl != PIN_UNUSED) {
pwm_config cfg = pwm_get_default_config();
pwm_set_wrap(pwm_gpio_to_slice_num(bl), 65535);
pwm_init(pwm_gpio_to_slice_num(bl), &cfg, true);
gpio_set_function(bl, GPIO_FUNC_PWM);
set_backlight(0); // Turn backlight off initially to avoid nasty surprises
}
}
};
}