WIP display doublebuffer

This commit is contained in:
Pavol Rusnak 2018-02-17 15:43:04 +01:00
parent db141fbc14
commit cfd777dca4
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
4 changed files with 201 additions and 18 deletions

View File

@ -21,9 +21,66 @@
#define CMD(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE))) = (X))
#define DATA(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | (1 << DISPLAY_MEMORY_PIN)))) = (X))
#define PIXELDATA(X) DATA((X) >> 8); DATA((X) & 0xFF)
#define LED_PWM_TIM_PERIOD (10000)
#define DOUBLE_BUFFER 1
#if DOUBLE_BUFFER
__IO uint8_t *DBUF = (__IO uint8_t *)CCMDATARAM_BASE;
secbool DBUF_DIRTY = sectrue;
static struct {
struct {
uint16_t x, y;
} start;
struct {
uint16_t x, y;
} end;
struct {
uint16_t x, y;
} pos;
} PIXELWINDOW;
static void PIXELDATA(uint16_t c)
{
// convert from 16-bit depth to 8-bit depth
// (RBB: 5-6-5 bits to 3-3-2 bits: rrrrrggg gggbbbbb -> rrrgggbb)
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) {
const int i = PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * DISPLAY_RESX;
if (i < DISPLAY_RESX * DISPLAY_RESY) {
const uint8_t d = ((c & 0xE000) >> 8) | ((c & 0x700) >> 6) | ((c & 0x18) >> 3);
DBUF[i] = d;
DBUF_DIRTY = sectrue;
}
}
PIXELWINDOW.pos.x++;
if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) {
PIXELWINDOW.pos.x = PIXELWINDOW.start.x;
PIXELWINDOW.pos.y++;
}
}
#else
#define PIXELDATA(X) DATA((X) >> 8); DATA((X) & 0xFF)
#endif
static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void display_clear(void)
{
const int saved_orientation = DISPLAY_ORIENTATION;
display_orientation(0); // set MADCTL first so that we can set the window correctly next
display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1); // address the complete frame memory
for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) {
DATA(0x00); DATA(0x00); // 2 bytes per pixel because we're using RGB 5-6-5 format
}
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // go back to restricted window
display_orientation(saved_orientation); // if valid, go back to the saved orientation
#if DOUBLE_BUFFER
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
PIXELDATA(0x0000);
}
#endif
}
static void __attribute__((unused)) display_sleep(void)
{
@ -51,15 +108,28 @@ static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y
{
x0 += BUFFER_OFFSET.x; x1 += BUFFER_OFFSET.x;
y0 += BUFFER_OFFSET.y; y1 += BUFFER_OFFSET.y;
#if DOUBLE_BUFFER
PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0;
PIXELWINDOW.end.x = x1; PIXELWINDOW.end.y = y1;
PIXELWINDOW.pos.x = x0; PIXELWINDOW.pos.y = y0;
#else
#if DISPLAY_ILI9341V || DISPLAY_ST7789V
CMD(0x2A); DATA(x0 >> 8); DATA(x0 & 0xFF); DATA(x1 >> 8); DATA(x1 & 0xFF); // column addr set
CMD(0x2B); DATA(y0 >> 8); DATA(y0 & 0xFF); DATA(y1 >> 8); DATA(y1 & 0xFF); // row addr set
CMD(0x2C);
#endif
#endif
}
void display_set_orientation(int degrees)
{
#if DOUBLE_BUFFER
#else
#if DISPLAY_ILI9341V || DISPLAY_ST7789V
#define MV (1 << 5)
#define MX (1 << 6)
@ -88,8 +158,12 @@ void display_set_orientation(int degrees)
CMD(0x36); DATA(display_command_parameter);
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // reset the column and page extents
#endif
#endif
}
#define LED_PWM_TIM_PERIOD (10000)
void display_set_backlight(int val)
{
TIM1->CCR1 = LED_PWM_TIM_PERIOD * val / 255;
@ -257,6 +331,101 @@ void display_refresh(void)
// synchronize with the panel synchronization signal in order to avoid visual tearing effects
while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { }
while (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { }
#if DOUBLE_BUFFER
// don't draw if not dirty
if (sectrue != DBUF_DIRTY) return;
// frame limiter = don't redraw frame if older one is younger than 16 ms = 60 fps
static uint32_t t0 = 0;
uint32_t t1 = HAL_GetTick();
if (t1 < t0 + 16) {
t0 = t1;
return;
} else {
t0 = t1;
}
static const uint16_t rgb332to565lut[256] = {
0x0000, 0x000a, 0x0015, 0x001f, 0x0120, 0x012a, 0x0135, 0x013f,
0x0240, 0x024a, 0x0255, 0x025f, 0x0360, 0x036a, 0x0375, 0x037f,
0x0480, 0x048a, 0x0495, 0x049f, 0x05a0, 0x05aa, 0x05b5, 0x05bf,
0x06c0, 0x06ca, 0x06d5, 0x06df, 0x07e0, 0x07ea, 0x07f5, 0x07ff,
0x2000, 0x200a, 0x2015, 0x201f, 0x2120, 0x212a, 0x2135, 0x213f,
0x2240, 0x224a, 0x2255, 0x225f, 0x2360, 0x236a, 0x2375, 0x237f,
0x2480, 0x248a, 0x2495, 0x249f, 0x25a0, 0x25aa, 0x25b5, 0x25bf,
0x26c0, 0x26ca, 0x26d5, 0x26df, 0x27e0, 0x27ea, 0x27f5, 0x27ff,
0x4800, 0x480a, 0x4815, 0x481f, 0x4920, 0x492a, 0x4935, 0x493f,
0x4a40, 0x4a4a, 0x4a55, 0x4a5f, 0x4b60, 0x4b6a, 0x4b75, 0x4b7f,
0x4c80, 0x4c8a, 0x4c95, 0x4c9f, 0x4da0, 0x4daa, 0x4db5, 0x4dbf,
0x4ec0, 0x4eca, 0x4ed5, 0x4edf, 0x4fe0, 0x4fea, 0x4ff5, 0x4fff,
0x6800, 0x680a, 0x6815, 0x681f, 0x6920, 0x692a, 0x6935, 0x693f,
0x6a40, 0x6a4a, 0x6a55, 0x6a5f, 0x6b60, 0x6b6a, 0x6b75, 0x6b7f,
0x6c80, 0x6c8a, 0x6c95, 0x6c9f, 0x6da0, 0x6daa, 0x6db5, 0x6dbf,
0x6ec0, 0x6eca, 0x6ed5, 0x6edf, 0x6fe0, 0x6fea, 0x6ff5, 0x6fff,
0x9000, 0x900a, 0x9015, 0x901f, 0x9120, 0x912a, 0x9135, 0x913f,
0x9240, 0x924a, 0x9255, 0x925f, 0x9360, 0x936a, 0x9375, 0x937f,
0x9480, 0x948a, 0x9495, 0x949f, 0x95a0, 0x95aa, 0x95b5, 0x95bf,
0x96c0, 0x96ca, 0x96d5, 0x96df, 0x97e0, 0x97ea, 0x97f5, 0x97ff,
0xb000, 0xb00a, 0xb015, 0xb01f, 0xb120, 0xb12a, 0xb135, 0xb13f,
0xb240, 0xb24a, 0xb255, 0xb25f, 0xb360, 0xb36a, 0xb375, 0xb37f,
0xb480, 0xb48a, 0xb495, 0xb49f, 0xb5a0, 0xb5aa, 0xb5b5, 0xb5bf,
0xb6c0, 0xb6ca, 0xb6d5, 0xb6df, 0xb7e0, 0xb7ea, 0xb7f5, 0xb7ff,
0xd800, 0xd80a, 0xd815, 0xd81f, 0xd920, 0xd92a, 0xd935, 0xd93f,
0xda40, 0xda4a, 0xda55, 0xda5f, 0xdb60, 0xdb6a, 0xdb75, 0xdb7f,
0xdc80, 0xdc8a, 0xdc95, 0xdc9f, 0xdda0, 0xddaa, 0xddb5, 0xddbf,
0xdec0, 0xdeca, 0xded5, 0xdedf, 0xdfe0, 0xdfea, 0xdff5, 0xdfff,
0xf800, 0xf80a, 0xf815, 0xf81f, 0xf920, 0xf92a, 0xf935, 0xf93f,
0xfa40, 0xfa4a, 0xfa55, 0xfa5f, 0xfb60, 0xfb6a, 0xfb75, 0xfb7f,
0xfc80, 0xfc8a, 0xfc95, 0xfc9f, 0xfda0, 0xfdaa, 0xfdb5, 0xfdbf,
0xfec0, 0xfeca, 0xfed5, 0xfedf, 0xffe0, 0xffea, 0xfff5, 0xffff,
};
// set full window
const uint16_t x0 = 0, y0 = 0, x1 = DISPLAY_RESX - 1, y1 = DISPLAY_RESY - 1;
CMD(0x2A); DATA(x0 >> 8); DATA(x0 & 0xFF); DATA(x1 >> 8); DATA(x1 & 0xFF); // column addr set
CMD(0x2B); DATA(y0 >> 8); DATA(y0 & 0xFF); DATA(y1 >> 8); DATA(y1 & 0xFF); // row addr set
CMD(0x2C);
// flush double buffer according to orientation
// also convert from 8-bit depth to 16-bit depth
// (RBB: 3-3-2 bits to 5-6-5 bits: rrrgggbb -> rrrrrggg gggbbbbb)
switch (DISPLAY_ORIENTATION) {
case 0:
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
const uint16_t d = rgb332to565lut[DBUF[i]];
DATA(d >> 8); DATA(d & 0xFF);
}
break;
case 90:
for (int j = 0; j < DISPLAY_RESY; j++) {
for (int i = 0; i < DISPLAY_RESX; i++) {
const int o = (DISPLAY_RESX - 1 - i) * DISPLAY_RESY + j;
const uint16_t d = rgb332to565lut[DBUF[o]];
DATA(d >> 8); DATA(d & 0xFF);
}
}
break;
case 180:
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
const int o = DISPLAY_RESX * DISPLAY_RESY - 1 - i;
const uint16_t d = rgb332to565lut[DBUF[o]];
DATA(d >> 8); DATA(d & 0xFF);
}
break;
case 270:
for (int j = 0; j < DISPLAY_RESY; j++) {
for (int i = 0; i < DISPLAY_RESX; i++) {
const int o = i * DISPLAY_RESY + (DISPLAY_RESY - 1 - j);
const uint16_t d = rgb332to565lut[DBUF[o]];
DATA(d >> 8); DATA(d & 0xFF);
}
}
break;
}
DBUF_DIRTY = secfalse;
#endif
}
void display_save(const char *filename)

View File

@ -30,8 +30,25 @@ void PIXELDATA(uint16_t c) {
if (!RENDERER) {
display_init();
}
int r = ((c & 0xF800) >> 11) * 255 / 31;
int g = ((c & 0x07E0) >> 5) * 255 / 63;
int b = (c & 0x1F) * 255 / 31;
#define BITS_R 3
#define BITS_G 3
#define BITS_B 2
r >>= (8 - BITS_R);
g >>= (8 - BITS_G);
b >>= (8 - BITS_B);
r = r * 255 / ((1 << BITS_R) - 1);
g = g * 255 / ((1 << BITS_G) - 1);
b = b * 255 / ((1 << BITS_B) - 1);
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) {
((uint16_t *)BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch / sizeof(uint16_t)] = c;
((uint16_t *)BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch / sizeof(uint16_t)] = RGB16(r, g, b);
}
PIXELWINDOW.pos.x++;
if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) {
@ -43,6 +60,17 @@ void PIXELDATA(uint16_t c) {
#define PIXELDATA(X) (void)(X)
#endif
void display_clear(void)
{
#ifndef TREZOR_NOUI
if (!RENDERER) {
display_init();
}
SDL_FillRect(BUFFER, NULL, SDL_MapRGB(BUFFER->format, 0, 0, 0));
SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch);
#endif
}
void display_init(void)
{
#ifndef TREZOR_NOUI

View File

@ -67,18 +67,6 @@ static inline void clamp_coords(int x, int y, int w, int h, int *x0, int *y0, in
*y1 = MIN(y + h - 1, DISPLAY_RESY - 1);
}
void display_clear(void)
{
const int saved_orientation = DISPLAY_ORIENTATION;
display_orientation(0); // set MADCTL first so that we can set the window correctly next
display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1); // address the complete frame memory
for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) {
PIXELDATA(0x0000); // 2 bytes per pixel because we're using RGB 5-6-5 format
}
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // go back to restricted window
display_orientation(saved_orientation); // if valid, go back to the saved orientation
}
void display_bar(int x, int y, int w, int h, uint16_t c)
{
x += DISPLAY_OFFSET.x;

View File

@ -13,9 +13,7 @@ from trezor import workflow
display = Display()
# for desktop platforms, we need to refresh the display after each frame
if sys.platform != 'trezor':
loop.after_step_hook = display.refresh
loop.after_step_hook = display.refresh
# import constants from modtrezorui