pull/1/head
Jonathan Williamson 2021-01-15 16:12:36 +00:00
rodzic 88ceb123b4
commit cf86122d56
2 zmienionych plików z 222 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,151 @@
#include "st7789.hpp"
#include "hardware/dma.h"
namespace pimoroni {
void ST7789::init() {
spi_init(spi, spi_baud);
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 framesync is enabled then the fs pin is toggled
// high during vsync
if(vsync != -1) {
gpio_set_function(fs, GPIO_FUNC_SIO);
gpio_set_dir(fs, GPIO_IN);
gpio_set_pulls(fs, false, true)
}
// if a backlight pin is provided then set it up for
// pwm control
if(bl != -1) {
pwm_config cfg = pwm_get_default_config();
pwm_config_wrap(&cfg, 65535);
pwm_init(pwm_gpio_to_slice(bl), &cfg, true);
gpio_set_function(bl, GPIO_FUNC_PWM);
}
gpio_set_function(sck, GPIO_FUNC_SPI);
gpio_set_function(mosi, GPIO_FUNC_SPI);
if(miso != -1) {
gpio_set_function(miso, GPIO_FUNC_SPI);
}
// initialise dma channel for transmitting pixel data to screen
dma_channel = dma_claim_unused_channel(true);
dma_channel_config config = dma_channel_get_default_config(dma_channel);
//channel_config_set_bswap(&config, true); // byte swap to reverse little endian
dma_channel_configure(
dma_channel,
&config,
&spi_get_hw(spi)->dr,
buffer,
sizeof(uint16_t) * width * height,
false);
}
void ST7789::init_240x240() {
init();
width = 240;
height = 240;
row_stride = width * sizeof(uint16_t);
// only initialise the buffer if one hasn't been supplied
if(!buffer) {
buffer = malloc(sizeof(uint16_t) * width * height);
}
// initialise our standard 240x240 LCD as 16-bit colour
// with an RGB subpixel element order.
command(register::SWRESET);
sleep_ms(150);
command(register::MADCTL, 1, "\x04"); // row/column addressing order - rgb pixel order
command(register::TEON, 1, "\x00"); // enable frame sync signal if used
command(register::COLMOD, 1, "\x05"); // 16 bits per pixel
command(register::SLPOUT); // leave sleep mode
command(register::DISPON); // turn display on
sleep_ms(100);
// set writing "window" to the full display
command(register::CASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 columns
command(register::RASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 rows
// put into write mode
command(register::RAMWR);
}
void ST7789::init_240x135() {
init();
width = 240;
height = 135;
row_stride = width * sizeof(uint16_t);
// only initialise the buffer if one hasn't been supplied
if(!buffer) {
buffer = malloc(sizeof(uint16_t) * width * height);
}
// initialise our standard 240x135 LCD as 16-bit colour
// with an RGB subpixel element order.
command(register::SWRESET);
sleep_ms(150);
command(register::MADCTL, 1, "\x70");
command(register::COLMOD, 1, "\x05");
command(register::SLPOUT); // leave sleep mode
command(register::DISPON); // turn display on
sleep_ms(100);
command(register::RASET, 4, "\x00\x35\x00\xbb"); // 53 .. 187 (135 rows)
command(register::CASET, 4, "\x00\x28\x01\x17"); // 40 .. 279 (240 columns)
}
void ST7789::command(uint8_t command, size_t len = 0, const char *data = NULL) {
gpio_put(pin::CS, 0);
gpio_put(pin::DC, 0); // command mode
spi_write_blocking(spi0, &command, 1);
if(data) {
gpio_put(pin::DC, 1); // data mode
spi_write_blocking(spi0, (const uint8_t*)data, len);
}
gpio_put(pin::CS, 1);
}
void ST7789::update() {
dma_channel_wait_for_finish_blocking(dma_channel);
command(register::RAMWR);
dma_channel_start(dma_channel);
}
void ST7789::set_backlight(uint8_t brightness) {
// gamma correct the provided 0-255 brightness value onto a
// 0-65535 range for the pwm counter
float gamma = 2.8;
uint16_t value = (uint16_t)(pow((float)(brightness) / 255.0f, gamma) * 65536.0f + 0.5f);
pwm_set_gpio_level(bl, value);
}
void ST7789::vsync_callback(gpio_irq_callback_t callback) {
gpio_set_irq_enabled_with_callback(vsync, GPIO_IRQ_EDGE_RISE, true, &callback);
}
}

Wyświetl plik

@ -0,0 +1,71 @@
#pragma once
#include "hardware/spi.h"
namespace pimoroni {
class ST7789 {
spi_inst_t *spi = spi0_hw;
// framebuffer for storing pixel data
uint16_t *buffer;
uint32_t dma_channel;
// screen properties
uint16_t width;
uint16_t height;
uint16_t row_stride;
// interface pins with our standard defaults where appropriate
int8_t sck = 18;
int8_t mosi = 19;
int8_t miso = -1; // we generally don't use this pin
int8_t cs = 17;
int8_t dc = 16;
int8_t bl = 20;
int8_t vsync = -1; // only available on some products
uint32_t spi_baud = 64 * 1024 * 1024;
public:
ST7789(spi_inst_t *spi, uint8_t cs, uint8_t dc, uint8_t sck, uint8_t mosi, uint8_t miso = -1) :
spi(spi), cs(cs), dc(dc), sck(sck), mosi(mosi), miso(miso) {}
void init();
void init_240x240();
void init_240x235();
void vsync_callback(gpio_irq_callback_t callback);
void update();
uint16_t pen(uint8_t r, uint8_t g, uint8_t b);
enum register {
SWRESET = 0x01,
TEON = 0x35,
MADCTL = 0x36,
COLMOD = 0x3A,
GCTRL = 0xB7,
VCOMS = 0xBB,
LCMCTRL = 0xC0,
VDVVRHEN = 0xC2,
VRHS = 0xC3,
VDVS = 0xC4,
FRCTRL2 = 0xC6,
PWRCTRL1 = 0xD0,
FRMCTR1 = 0xB1,
FRMCTR2 = 0xB2,
GMCTRP1 = 0xE0,
GMCTRN1 = 0xE1,
INVOFF = 0x20,
SLPOUT = 0x11,
DISPON = 0x29,
GAMSET = 0x26,
DISPOFF = 0x28,
RAMWR = 0x2C,
INVON = 0x21,
CASET = 0x2A,
RASET = 0x2B
};
};
}