Encode symbols for palette rather than relying on hardcoded values. Allows 24-bit colour values.

pull/17/head
Mike Bell 2021-03-19 12:53:26 +00:00 zatwierdzone przez Luke Wren
rodzic 1203673e5c
commit 8e5f53625c
3 zmienionych plików z 66 dodań i 14 usunięć

Wyświetl plik

@ -569,7 +569,7 @@ decl_func_y tmds_fullres_encode_loop_16bpp_leftshift_y
b 2f
.align 2
1:
.rept 8
.rept 10
ldmia r0!, {r3, r5}
lsrs r4, r3, #14
lsls r3, #2

Wyświetl plik

@ -19,10 +19,6 @@ const uint32_t __scratch_y("tmds_table_fullres_y") tmds_table_fullres_y[] = {
#include "tmds_table_fullres.h"
};
const uint32_t tmds_table_fullres_noncritical[] = {
#include "tmds_table_fullres.h"
};
// Configure an interpolator to extract a single colour channel from each of a pair
// of pixels, with the first pixel's lsb at pixel_lsb, and the pixels being
// pixel_width wide. Produce a LUT address for the first pixel's colour data on
@ -171,6 +167,46 @@ void __not_in_flash_func(tmds_encode_data_channel_fullres_16bpp)(const uint32_t
#endif
}
static const int8_t imbalance_lookup[16] = { -4, -2, -2, 0, -2, 0, 0, 2, -2, 0, 0, 2, 0, 2, 2, 4 };
static inline int byte_imbalance(uint32_t x)
{
return imbalance_lookup[x >> 4] + imbalance_lookup[x & 0xF];
}
static void tmds_encode_symbols(uint8_t pixel, uint32_t* negative_balance_sym, uint32_t* positive_balance_sym)
{
int pixel_imbalance = byte_imbalance(pixel);
uint32_t sym = pixel & 1;
if (pixel_imbalance > 0 || (pixel_imbalance == 0 && sym == 0)) {
for (int i = 0; i < 7; ++i) {
sym |= (~((sym >> i) ^ (pixel >> (i + 1))) & 1) << (i + 1);
}
}
else {
for (int i = 0; i < 7; ++i) {
sym |= ( ((sym >> i) ^ (pixel >> (i + 1))) & 1) << (i + 1);
}
sym |= 0x100;
}
int imbalance = byte_imbalance(sym & 0xFF);
if (imbalance == 0) {
if ((sym & 0x100) == 0) sym ^= 0x2ff;
*positive_balance_sym = sym;
*negative_balance_sym = sym;
return;
}
else if (imbalance > 0) {
*negative_balance_sym = (sym ^ 0x2ff) | (((-imbalance + imbalance_lookup[2 ^ (sym >> 8)] + 2) & 0x3F) << 26);
*positive_balance_sym = sym | ((imbalance + imbalance_lookup[sym >> 8] + 2) << 26);
}
else {
*negative_balance_sym = sym | (((imbalance + imbalance_lookup[sym >> 8] + 2) & 0x3F) << 26);
*positive_balance_sym = (sym ^ 0x2ff) | ((-imbalance + imbalance_lookup[2 ^ (sym >> 8)] + 2) << 26);
}
}
// This takes a 16-bit (RGB 565) colour palette and makes palettes of TMDS symbols suitable
// for performing fullres encode.
// The TMDS palette buffer should be 6 * n_palette words long.
@ -180,15 +216,30 @@ void tmds_setup_palette_symbols(const uint16_t *palette, uint32_t *tmds_palette,
uint32_t* tmds_palette_green = tmds_palette + 2 * n_palette;
uint32_t* tmds_palette_red = tmds_palette + 4 * n_palette;
for (int i = 0; i < n_palette; ++i) {
uint16_t blue = (palette[i] << 1) & 0x3e;
uint16_t green = (palette[i] >> 5) & 0x3f;
uint16_t red = (palette[i] >> 10) & 0x3e;
tmds_palette_blue[i] = tmds_table_fullres_noncritical[blue];
tmds_palette_blue[i + n_palette] = tmds_table_fullres_noncritical[64 + blue];
tmds_palette_green[i] = tmds_table_fullres_noncritical[green];
tmds_palette_green[i + n_palette] = tmds_table_fullres_noncritical[64 + green];
tmds_palette_red[i] = tmds_table_fullres_noncritical[red];
tmds_palette_red[i + n_palette] = tmds_table_fullres_noncritical[64 + red];
uint16_t blue = (palette[i] << 3) & 0xf8;
uint16_t green = (palette[i] >> 3) & 0xfc;
uint16_t red = (palette[i] >> 8) & 0xf8;
tmds_encode_symbols(blue, &tmds_palette_blue[i], &tmds_palette_blue[i + n_palette]);
tmds_encode_symbols(green, &tmds_palette_green[i], &tmds_palette_green[i + n_palette]);
tmds_encode_symbols(red, &tmds_palette_red[i], &tmds_palette_red[i + n_palette]);
}
}
// This takes a 24-bit (RGB 888) colour palette and makes palettes of TMDS symbols suitable
// for performing fullres encode.
// The TMDS palette buffer should be 6 * n_palette words long.
// n_palette must be a power of 2 <= 256.
void tmds_setup_palette24_symbols(const uint32_t *palette, uint32_t *tmds_palette, size_t n_palette) {
uint32_t* tmds_palette_blue = tmds_palette;
uint32_t* tmds_palette_green = tmds_palette + 2 * n_palette;
uint32_t* tmds_palette_red = tmds_palette + 4 * n_palette;
for (int i = 0; i < n_palette; ++i) {
uint16_t blue = palette[i] & 0xff;
uint16_t green = (palette[i] >> 8) & 0xff;
uint16_t red = (palette[i] >> 16) & 0xff;
tmds_encode_symbols(blue, &tmds_palette_blue[i], &tmds_palette_blue[i + n_palette]);
tmds_encode_symbols(green, &tmds_palette_green[i], &tmds_palette_green[i + n_palette]);
tmds_encode_symbols(red, &tmds_palette_red[i], &tmds_palette_red[i + n_palette]);
}
}

Wyświetl plik

@ -9,6 +9,7 @@ void tmds_encode_data_channel_16bpp(const uint32_t *pixbuf, uint32_t *symbuf, si
void tmds_encode_data_channel_8bpp(const uint32_t *pixbuf, uint32_t *symbuf, size_t n_pix, uint channel_msb, uint channel_lsb);
void tmds_encode_data_channel_fullres_16bpp(const uint32_t *pixbuf, uint32_t *symbuf, size_t n_pix, uint channel_msb, uint channel_lsb);
void tmds_setup_palette_symbols(const uint16_t *palette, uint32_t *symbuf, size_t n_palette);
void tmds_setup_palette24_symbols(const uint32_t *palette, uint32_t *symbuf, size_t n_palette);
void tmds_encode_palette_data(const uint32_t *pixbuf, const uint32_t *tmds_palette, uint32_t *symbuf, size_t n_pix, uint32_t palette_bits);
// Functions from tmds_encode.S