mt12864k: implement contrast control via INF8574A register (4 levels)

This commit is contained in:
Nick Gagin
2026-08-08 00:45:27 +03:00
parent 1dad5260cd
commit 9385d04650
2 changed files with 54 additions and 13 deletions
+33 -11
View File
@@ -102,22 +102,28 @@ static void u8x8_mt12864k_select(u8x8_t *u8x8, uint8_t adr)
u8x8->i2c_address = adr;
}
/* write a single byte to the INF8574A control register (0x3B, 8-bit 0x076).
The register is an 8 bit latch: every write sets all bits, so the value
must always contain the state of all other control bits (^RST, backlight,
P_ON) as well. */
static void u8x8_mt12864k_write_register(u8x8_t *u8x8, uint8_t value)
{
u8x8_mt12864k_select(u8x8, U8X8_MT12864K_REG_ADR);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, value);
u8x8_byte_EndTransfer(u8x8);
}
/* reset both LCD controllers through the INF8574A control register */
static void u8x8_mt12864k_reset(u8x8_t *u8x8)
{
u8x8_mt12864k_select(u8x8, U8X8_MT12864K_REG_ADR);
/* assert ^RST (bit 0 = 0), keep the other bits at their default value */
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, U8X8_MT12864K_REG_RESET);
u8x8_byte_EndTransfer(u8x8);
u8x8_mt12864k_write_register(u8x8, U8X8_MT12864K_REG_RESET);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, 1);
/* release ^RST (bit 0 = 1) */
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, U8X8_MT12864K_REG_DEFAULT);
u8x8_byte_EndTransfer(u8x8);
u8x8_mt12864k_write_register(u8x8, U8X8_MT12864K_REG_DEFAULT);
/* datasheet: 10 ms delay after ^RST goes inactive */
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, 10);
@@ -231,9 +237,25 @@ uint8_t u8x8_d_mt12864k_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
/* The MT-12864K controllers can not mirror the cols and rows, use U8g2 for rotation */
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
// break;
/* The MT-12864K has no internal contrast command, contrast is controlled by the INF8574A register */
// case U8X8_MSG_DISPLAY_SET_CONTRAST:
// break;
/* The MT-12864K has no internal contrast command. Contrast is controlled by
the INF8574A register bits 4-6. The datasheet (table 4) defines only four
discrete levels, the CT_* bits are mutually exclusive: when one of them is
"0" the other two must be "1". Bits 0-3 (^RST, backlight, P_ON) and bit 7
stay at their default value "1". */
case U8X8_MSG_DISPLAY_SET_CONTRAST:
{
uint8_t ct;
if ( arg_int < 64 )
ct = 0x060; /* CT_LOW: contrast reduced */
else if ( arg_int < 128 )
ct = 0x070; /* normal contrast */
else if ( arg_int < 192 )
ct = 0x050; /* CT_HIGH1: contrast slightly increased */
else
ct = 0x030; /* CT_HIGH2: contrast strongly increased */
u8x8_mt12864k_write_register(u8x8, 0x08f | ct);
}
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
v.ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+21 -2
View File
@@ -186,7 +186,26 @@ int main(void)
if ( !check_transfer(10, 0x078, d2, 2) ) ok = 0;
if ( !check_transfer(11, 0x07a, d2, 2) ) ok = 0;
/* 4. full buffer: left half 0x55, right half 0xaa, then send */
/* 4. contrast: single byte writes to the control register (0x076).
Only four discrete levels are available (datasheet table 4):
value 0..63 -> CT_LOW (reduced) register 0x0ef
value 64..127 -> normal register 0x0ff
value 128..191 -> CT_HIGH1 (slight incr.) register 0x0df
value 192..255 -> CT_HIGH2 (strong incr.) register 0x0bf
All boundary values are checked. */
{
const uint8_t contrast_values[] = { 0, 63, 64, 127, 128, 191, 192, 255 };
const uint8_t contrast_reg[] = { 0x0ef, 0x0ef, 0x0ff, 0x0ff,
0x0df, 0x0df, 0x0bf, 0x0bf };
int i;
for( i = 0; i < 8; i++ )
{
u8x8_SetContrast(u8g2_GetU8x8(&u8g2), contrast_values[i]);
if ( !check_transfer(12 + i, 0x076, &contrast_reg[i], 1) ) ok = 0;
}
}
/* 5. full buffer: left half 0x55, right half 0xaa, then send */
buf = u8g2_GetBufferPtr(&u8g2);
for( page = 0; page < 8; page++ )
{
@@ -210,7 +229,7 @@ int main(void)
cnt_data_r = 0;
data_bytes_l = 0;
data_bytes_r = 0;
t = 12; /* transfers 0..11 were init + power on */
t = 20; /* transfers 0..19 were init, power on and contrast */
for( page = 0; page < 8; page++ )
{
int chip;