ST7789: Support rotation for PD and PD2.
This commit is contained in:
parent
249f54fae4
commit
813b7a401a
|
@ -55,6 +55,8 @@ namespace pimoroni {
|
|||
};
|
||||
|
||||
void ST7789::init(bool auto_init_sequence, bool round, uint32_t spi_baud) {
|
||||
this->round = round;
|
||||
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, spi_baud);
|
||||
|
||||
|
@ -96,33 +98,29 @@ namespace pimoroni {
|
|||
|
||||
sleep_ms(150);
|
||||
|
||||
// Common init
|
||||
command(reg::TEON); // enable frame sync signal if used
|
||||
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
|
||||
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
|
||||
if(width == 240 && height == 240) {
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
command(reg::GCTRL, 1, "\x14");
|
||||
command(reg::VCOMS, 1, "\x37");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
command(reg::GMCTRP1, 14, "\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23");
|
||||
command(reg::GMCTRN1, 14, "\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23");
|
||||
}
|
||||
|
||||
if(width == 320 && height == 240) {
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
if((width == 320 && height == 240)
|
||||
|| (width == 240 && height == 320)) {
|
||||
command(reg::GCTRL, 1, "\x35");
|
||||
command(reg::VCOMS, 1, "\x1f");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(0xd6, 1, "\xa1"); // ???
|
||||
command(reg::GMCTRP1, 14, "\xD0\x08\x11\x08\x0C\x15\x39\x33\x50\x36\x13\x14\x29\x2D");
|
||||
command(reg::GMCTRN1, 14, "\xD0\x08\x10\x08\x06\x06\x39\x44\x51\x0B\x16\x14\x2F\x31");
|
||||
|
@ -134,48 +132,7 @@ namespace pimoroni {
|
|||
|
||||
sleep_ms(100);
|
||||
|
||||
// setup correct addressing window
|
||||
if(width == 240 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 239;
|
||||
raset[0] = round ? 40 : 0;
|
||||
raset[1] = round ? 279 : 239;
|
||||
madctl = MADCTL::HORIZ_ORDER;
|
||||
}
|
||||
|
||||
if(width == 240 && height == 135) {
|
||||
caset[0] = 40; // 240 cols
|
||||
caset[1] = 279;
|
||||
raset[0] = 53; // 135 rows
|
||||
raset[1] = 187;
|
||||
madctl = MADCTL::COL_ORDER | MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
|
||||
}
|
||||
|
||||
if(width == 135 && height == 240) {
|
||||
caset[0] = 52; // 135 cols
|
||||
caset[1] = 186;
|
||||
raset[0] = 40; // 240 rows
|
||||
raset[1] = 279;
|
||||
madctl = 0;
|
||||
}
|
||||
|
||||
if(width == 320 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 319;
|
||||
raset[0] = 0;
|
||||
raset[1] = 239;
|
||||
madctl = 0x70;
|
||||
}
|
||||
|
||||
// Byte swap the 16bit rows/cols values
|
||||
caset[0] = __builtin_bswap16(caset[0]);
|
||||
caset[1] = __builtin_bswap16(caset[1]);
|
||||
raset[0] = __builtin_bswap16(raset[0]);
|
||||
raset[1] = __builtin_bswap16(raset[1]);
|
||||
|
||||
command(reg::CASET, 4, (char *)caset);
|
||||
command(reg::RASET, 4, (char *)raset);
|
||||
command(reg::MADCTL, 1, (char *)&madctl);
|
||||
configure_display(false);
|
||||
|
||||
if(bl != PIN_UNUSED) {
|
||||
update(); // Send the new buffer to the display to clear any previous content
|
||||
|
@ -205,6 +162,65 @@ namespace pimoroni {
|
|||
// dma_channel, &config, &spi_get_hw(spi)->dr, frame_buffer, width * height, false);
|
||||
}
|
||||
|
||||
void ST7789::configure_display(bool rotate180) {
|
||||
// setup correct addressing window
|
||||
if(width == 240 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 239;
|
||||
raset[0] = round ? 40 : 0;
|
||||
raset[1] = round ? 279 : 239;
|
||||
madctl = MADCTL::HORIZ_ORDER;
|
||||
}
|
||||
|
||||
// Pico Display
|
||||
if(width == 240 && height == 135) {
|
||||
caset[0] = 40; // 240 cols
|
||||
caset[1] = 279;
|
||||
raset[0] = 53; // 135 rows
|
||||
raset[1] = 187;
|
||||
madctl = rotate180 ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
|
||||
madctl |= MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
|
||||
}
|
||||
|
||||
// Pico Display at 90 degree rotation
|
||||
if(width == 135 && height == 240) {
|
||||
caset[0] = 52; // 135 cols
|
||||
caset[1] = 186;
|
||||
raset[0] = 40; // 240 rows
|
||||
raset[1] = 279;
|
||||
madctl = rotate180 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
|
||||
}
|
||||
|
||||
// Pico Display 2.0
|
||||
if(width == 320 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 319;
|
||||
raset[0] = 0;
|
||||
raset[1] = 239;
|
||||
madctl = rotate180 ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
|
||||
madctl |= MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
|
||||
}
|
||||
|
||||
// Pico Display 2.0 at 90 degree rotation
|
||||
if(width == 240 && height == 320) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 239;
|
||||
raset[0] = 0;
|
||||
raset[1] = 319;
|
||||
madctl = rotate180 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
|
||||
}
|
||||
|
||||
// Byte swap the 16bit rows/cols values
|
||||
caset[0] = __builtin_bswap16(caset[0]);
|
||||
caset[1] = __builtin_bswap16(caset[1]);
|
||||
raset[0] = __builtin_bswap16(raset[0]);
|
||||
raset[1] = __builtin_bswap16(raset[1]);
|
||||
|
||||
command(reg::CASET, 4, (char *)caset);
|
||||
command(reg::RASET, 4, (char *)raset);
|
||||
command(reg::MADCTL, 1, (char *)&madctl);
|
||||
}
|
||||
|
||||
spi_inst_t* ST7789::get_spi() const {
|
||||
return spi;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace pimoroni {
|
|||
// screen properties
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
bool round;
|
||||
uint16_t row_stride;
|
||||
uint32_t dma_channel;
|
||||
|
||||
|
@ -33,6 +34,7 @@ namespace pimoroni {
|
|||
// 16 ns = 62,500,000 Hz
|
||||
static const uint32_t SPI_BAUD = 62'500'000;
|
||||
|
||||
|
||||
public:
|
||||
// frame buffer where pixel data is stored
|
||||
uint16_t *frame_buffer;
|
||||
|
@ -74,6 +76,7 @@ namespace pimoroni {
|
|||
//--------------------------------------------------
|
||||
public:
|
||||
void init(bool auto_init_sequence = true, bool round = false, uint32_t spi_baud = SPI_BAUD);
|
||||
void configure_display(bool rotate180);
|
||||
|
||||
spi_inst_t* get_spi() const;
|
||||
uint get_cs() const;
|
||||
|
|
|
@ -56,4 +56,8 @@ namespace pimoroni {
|
|||
void ST7789Generic::set_backlight(uint8_t brightness) {
|
||||
st7789.set_backlight(brightness);
|
||||
}
|
||||
|
||||
void ST7789Generic::configure_display(bool rotate180) {
|
||||
st7789.configure_display(rotate180);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace pimoroni {
|
|||
void update();
|
||||
void flip();
|
||||
void set_backlight(uint8_t brightness);
|
||||
void configure_display(bool rotate180);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -51,10 +51,11 @@ void GenericST7789_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
|
|||
mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
GenericST7789_obj_t *self = nullptr;
|
||||
|
||||
enum { ARG_width, ARG_height, ARG_slot, ARG_buffer, ARG_spi, ARG_cs, ARG_dc, ARG_sck, ARG_mosi, ARG_bl };
|
||||
enum { ARG_width, ARG_height, ARG_rotate180, ARG_slot, ARG_buffer, ARG_spi, ARG_cs, ARG_dc, ARG_sck, ARG_mosi, ARG_bl };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_rotate180, MP_ARG_OBJ, {.u_obj = mp_const_false} },
|
||||
{ MP_QSTR_slot, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_buffer, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_spi, MP_ARG_INT, {.u_int = -1} },
|
||||
|
@ -72,6 +73,7 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
self = m_new_obj(GenericST7789_obj_t);
|
||||
self->base.type = &GenericST7789_type;
|
||||
|
||||
bool rotate180 = args[ARG_rotate180].u_obj == mp_const_true;
|
||||
int width = args[ARG_width].u_int;
|
||||
int height = args[ARG_height].u_int;
|
||||
|
||||
|
@ -90,6 +92,9 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
if(args[ARG_slot].u_int != -1) {
|
||||
BG_SPI_SLOT slot = (BG_SPI_SLOT)args[ARG_slot].u_int;
|
||||
self->st7789 = new ST7789Generic(width, height, slot, buffer);
|
||||
if (rotate180) {
|
||||
self->st7789->configure_display(true);
|
||||
}
|
||||
} else {
|
||||
// Get SPI bus.
|
||||
int spi_id = args[ARG_spi].u_int;
|
||||
|
@ -117,6 +122,9 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
self->st7789 = new ST7789Generic(width, height, spi,
|
||||
cs, dc, sck, mosi, PIN_UNUSED, bl,
|
||||
buffer);
|
||||
if (rotate180) {
|
||||
self->st7789->configure_display(true);
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
|
|
Loading…
Reference in New Issue