Compare commits

..

1 Commits

Author SHA1 Message Date
Remco van Essen
4906f87751 [mipi_dsi] add JC8012P4A1 (#13241) 2026-01-16 21:17:32 +11:00
3 changed files with 270 additions and 38 deletions

View File

@@ -101,4 +101,225 @@ DriverChip(
(0xFF, 0x77, 0x01, 0x00, 0x00, 0x00),
]
)
# jc8012P4A1 Driver Configuration (jd9365)
# Using parameters from esp_lcd_jd9365.h and the working full init sequence
# ----------------------------------------------------------------------------------------------------------------------
# * Resolution: 800x1280
# * PCLK Frequency: 60 MHz
# * DSI Lane Bit Rate: 1 Gbps (using 2-Lane DSI configuration)
# * Horizontal Timing (hsync_pulse_width=20, hsync_back_porch=20, hsync_front_porch=40)
# * Vertical Timing (vsync_pulse_width=4, vsync_back_porch=8, vsync_front_porch=20)
# ----------------------------------------------------------------------------------------------------------------------
DriverChip(
"JC8012P4A1",
width=800,
height=1280,
hsync_back_porch=20,
hsync_pulse_width=20,
hsync_front_porch=40,
vsync_back_porch=8,
vsync_pulse_width=4,
vsync_front_porch=20,
pclk_frequency="60MHz",
lane_bit_rate="1Gbps",
swap_xy=cv.UNDEFINED,
color_order="RGB",
reset_pin=27,
initsequence=[
(0xE0, 0x00),
(0xE1, 0x93),
(0xE2, 0x65),
(0xE3, 0xF8),
(0x80, 0x01),
(0xE0, 0x01),
(0x00, 0x00),
(0x01, 0x39),
(0x03, 0x10),
(0x04, 0x41),
(0x0C, 0x74),
(0x17, 0x00),
(0x18, 0xD7),
(0x19, 0x00),
(0x1A, 0x00),
(0x1B, 0xD7),
(0x1C, 0x00),
(0x24, 0xFE),
(0x35, 0x26),
(0x37, 0x69),
(0x38, 0x05),
(0x39, 0x06),
(0x3A, 0x08),
(0x3C, 0x78),
(0x3D, 0xFF),
(0x3E, 0xFF),
(0x3F, 0xFF),
(0x40, 0x06),
(0x41, 0xA0),
(0x43, 0x14),
(0x44, 0x0B),
(0x45, 0x30),
(0x4B, 0x04),
(0x55, 0x02),
(0x57, 0x89),
(0x59, 0x0A),
(0x5A, 0x28),
(0x5B, 0x15),
(0x5D, 0x50),
(0x5E, 0x37),
(0x5F, 0x29),
(0x60, 0x1E),
(0x61, 0x1D),
(0x62, 0x12),
(0x63, 0x1A),
(0x64, 0x08),
(0x65, 0x25),
(0x66, 0x26),
(0x67, 0x28),
(0x68, 0x49),
(0x69, 0x3A),
(0x6A, 0x43),
(0x6B, 0x3A),
(0x6C, 0x3B),
(0x6D, 0x32),
(0x6E, 0x1F),
(0x6F, 0x0E),
(0x70, 0x50),
(0x71, 0x37),
(0x72, 0x29),
(0x73, 0x1E),
(0x74, 0x1D),
(0x75, 0x12),
(0x76, 0x1A),
(0x77, 0x08),
(0x78, 0x25),
(0x79, 0x26),
(0x7A, 0x28),
(0x7B, 0x49),
(0x7C, 0x3A),
(0x7D, 0x43),
(0x7E, 0x3A),
(0x7F, 0x3B),
(0x80, 0x32),
(0x81, 0x1F),
(0x82, 0x0E),
(0xE0, 0x02),
(0x00, 0x1F),
(0x01, 0x1F),
(0x02, 0x52),
(0x03, 0x51),
(0x04, 0x50),
(0x05, 0x4B),
(0x06, 0x4A),
(0x07, 0x49),
(0x08, 0x48),
(0x09, 0x47),
(0x0A, 0x46),
(0x0B, 0x45),
(0x0C, 0x44),
(0x0D, 0x40),
(0x0E, 0x41),
(0x0F, 0x1F),
(0x10, 0x1F),
(0x11, 0x1F),
(0x12, 0x1F),
(0x13, 0x1F),
(0x14, 0x1F),
(0x15, 0x1F),
(0x16, 0x1F),
(0x17, 0x1F),
(0x18, 0x52),
(0x19, 0x51),
(0x1A, 0x50),
(0x1B, 0x4B),
(0x1C, 0x4A),
(0x1D, 0x49),
(0x1E, 0x48),
(0x1F, 0x47),
(0x20, 0x46),
(0x21, 0x45),
(0x22, 0x44),
(0x23, 0x40),
(0x24, 0x41),
(0x25, 0x1F),
(0x26, 0x1F),
(0x27, 0x1F),
(0x28, 0x1F),
(0x29, 0x1F),
(0x2A, 0x1F),
(0x2B, 0x1F),
(0x2C, 0x1F),
(0x2D, 0x1F),
(0x2E, 0x52),
(0x2F, 0x40),
(0x30, 0x41),
(0x31, 0x48),
(0x32, 0x49),
(0x33, 0x4A),
(0x34, 0x4B),
(0x35, 0x44),
(0x36, 0x45),
(0x37, 0x46),
(0x38, 0x47),
(0x39, 0x51),
(0x3A, 0x50),
(0x3B, 0x1F),
(0x3C, 0x1F),
(0x3D, 0x1F),
(0x3E, 0x1F),
(0x3F, 0x1F),
(0x40, 0x1F),
(0x41, 0x1F),
(0x42, 0x1F),
(0x43, 0x1F),
(0x44, 0x52),
(0x45, 0x40),
(0x46, 0x41),
(0x47, 0x48),
(0x48, 0x49),
(0x49, 0x4A),
(0x4A, 0x4B),
(0x4B, 0x44),
(0x4C, 0x45),
(0x4D, 0x46),
(0x4E, 0x47),
(0x4F, 0x51),
(0x50, 0x50),
(0x51, 0x1F),
(0x52, 0x1F),
(0x53, 0x1F),
(0x54, 0x1F),
(0x55, 0x1F),
(0x56, 0x1F),
(0x57, 0x1F),
(0x58, 0x40),
(0x59, 0x00),
(0x5A, 0x00),
(0x5B, 0x10),
(0x5C, 0x05),
(0x5D, 0x50),
(0x5E, 0x01),
(0x5F, 0x02),
(0x60, 0x50),
(0x61, 0x06),
(0x62, 0x04),
(0x63, 0x03),
(0x64, 0x64),
(0x65, 0x65),
(0x66, 0x0B),
(0x67, 0x73),
(0x68, 0x07),
(0x69, 0x06),
(0x6A, 0x64),
(0x6B, 0x08),
(0x6C, 0x00),
(0x6D, 0x32),
(0x6E, 0x08),
(0xE0, 0x04),
(0x2C, 0x6B),
(0x35, 0x08),
(0x37, 0x00),
(0xE0, 0x00),
]
)
# fmt: on

View File

@@ -624,44 +624,53 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
return ret;
}
/// Decode base64/base64url string directly into vector of little-endian int32 values
/// @param base64 Base64 or base64url encoded string (both +/ and -_ accepted)
/// @param out Output vector (cleared and filled with decoded int32 values)
/// @return true if successful, false if decode failed or invalid size
bool base64_decode_int32_vector(const std::string &base64, std::vector<int32_t> &out) {
// Decode in chunks to minimize stack usage
constexpr size_t chunk_bytes = 48; // 12 timings worth
constexpr size_t chunk_chars = 64; // 48 * 4/3 = 64 chars
uint8_t chunk[chunk_bytes];
/// Encode int32 to 5 base85 characters + null terminator
/// Standard ASCII85 alphabet: '!' (33) = 0 through 'u' (117) = 84
inline void base85_encode_int32(int32_t value, std::span<char, BASE85_INT32_ENCODED_SIZE> output) {
uint32_t v = static_cast<uint32_t>(value);
// Encode least significant digit first, then reverse
for (int i = 4; i >= 0; i--) {
output[i] = static_cast<char>('!' + (v % 85));
v /= 85;
}
output[5] = '\0';
}
/// Decode 5 base85 characters to int32
inline bool base85_decode_int32(const char *input, int32_t &out) {
uint8_t c0 = static_cast<uint8_t>(input[0] - '!');
uint8_t c1 = static_cast<uint8_t>(input[1] - '!');
uint8_t c2 = static_cast<uint8_t>(input[2] - '!');
uint8_t c3 = static_cast<uint8_t>(input[3] - '!');
uint8_t c4 = static_cast<uint8_t>(input[4] - '!');
// Each digit must be 0-84. Since uint8_t wraps, chars below '!' become > 84
if (c0 > 84 || c1 > 84 || c2 > 84 || c3 > 84 || c4 > 84)
return false;
// 85^4 = 52200625, 85^3 = 614125, 85^2 = 7225, 85^1 = 85
out = static_cast<int32_t>(c0 * 52200625u + c1 * 614125u + c2 * 7225u + c3 * 85u + c4);
return true;
}
/// Decode base85 string directly into vector (no intermediate buffer)
bool base85_decode_int32_vector(const std::string &base85, std::vector<int32_t> &out) {
size_t len = base85.size();
if (len % 5 != 0)
return false;
out.clear();
const char *ptr = base85.data();
const char *end = ptr + len;
const uint8_t *input = reinterpret_cast<const uint8_t *>(base64.data());
size_t remaining = base64.size();
size_t pos = 0;
while (remaining > 0) {
size_t chars_to_decode = std::min(remaining, chunk_chars);
size_t decoded_len = base64_decode(input + pos, chars_to_decode, chunk, chunk_bytes);
if (decoded_len == 0)
while (ptr < end) {
int32_t value;
if (!base85_decode_int32(ptr, value))
return false;
// Parse little-endian int32 values
for (size_t i = 0; i + 3 < decoded_len; i += 4) {
int32_t timing = static_cast<int32_t>(encode_uint32(chunk[i + 3], chunk[i + 2], chunk[i + 1], chunk[i]));
out.push_back(timing);
}
// Check for incomplete int32 in last chunk
if (remaining <= chunk_chars && (decoded_len % 4) != 0)
return false;
pos += chars_to_decode;
remaining -= chars_to_decode;
out.push_back(value);
ptr += 5;
}
return !out.empty();
return true;
}
// Colors

View File

@@ -1137,11 +1137,13 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string);
size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len);
size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len);
/// Decode base64/base64url string directly into vector of little-endian int32 values
/// @param base64 Base64 or base64url encoded string (both +/ and -_ accepted)
/// @param out Output vector (cleared and filled with decoded int32 values)
/// @return true if successful, false if decode failed or invalid size
bool base64_decode_int32_vector(const std::string &base64, std::vector<int32_t> &out);
/// Size of buffer needed for base85 encoded int32 (5 chars + null terminator)
static constexpr size_t BASE85_INT32_ENCODED_SIZE = 6;
void base85_encode_int32(int32_t value, std::span<char, BASE85_INT32_ENCODED_SIZE> output);
bool base85_decode_int32(const char *input, int32_t &out);
bool base85_decode_int32_vector(const std::string &base85, std::vector<int32_t> &out);
///@}