Open RSE-dev opened 3 months ago
It looks like that the CH1120 is a graylevel display, while SH1108 is a pure monochrome display. At least CH1120 needs to be configured as a monochrome display, see chapter 6.7.3 of the datasheet.
Did you compare the command table of both display? I think there are not so many similarities... Anyhow I will follow your apprach and create a copy of the SH1108 code...
I tookover the init sequence from the display datasheet. It is very much different to the SH1108. I really wonder that anything was visible with the SH1108 constructor.
I have created beta 2.35.25 with constructor U8G2_CH1120_128X160_1_4W_HW_SPI and friends
Maybe you can test this new constructor. I assume still a lot of work is required.
You can download the latest U8g2 beta release from here: https://github.com/olikraus/U8g2_Arduino/archive/master.zip Arduino IDE:
PlatformIO:
platformio.ini
(https://docs.platformio.org/en/latest/projectconf/section_env_library.html#lib-deps) should include
lib_deps =
u8g2=https://github.com/olikraus/U8g2_Arduino/archive/master.zip
I tested the new constructor. Unfortunately, the result is the same (or maybe just a little different image of the snow)
Moreover, I have to add that the testing is running on two different platforms:
For the future iterations, I'll run the code on both platforms to provide more information to you
Somehow it looks like that no data is transfered.
I tested the code with two displays. The modules are absolutely the same except for the driver IC. The pinout of the modules is the same, so I'm just swapping the modules and flashing the new code to the Arduino Mega.
The code is pretty basic, please find it here with comments
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
// U8G2_CH1120_128X160_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //doesn't work with CH1120 based display
// U8G2_CH1120_128X160_2_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //doesn't work with CH1120 based display
// U8G2_CH1120_128X160_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //doesn't work with CH1120 based display
// U8G2_SH1108_128X160_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //works fine with SH1108 based display
// U8G2_SH1108_128X160_2_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //works fine with SH1108 based display
U8G2_SH1108_128X160_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 42, /* dc=*/ 44, /* reset=*/ 46); //works fine with SH1108 based display
char buf[16];
void setup(void) {
u8g2.begin();
}
void loop(void) {
ltoa(millis(),buf,10);
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_ncenB10_tr);
u8g2.drawStr(0,24,"Hello World!");
u8g2.drawStr(0,50,buf);
} while ( u8g2.nextPage() );
delay(1000);
}
As the pinout of the modules is the same and the code works fine with the SH1108-based display, I assume, the connection is correct.
Ok, i found a remark in the datasheet and fixed the code based on this. Can you test the new beta (2.35.26) again ?
/ You can download the latest U8g2 beta release from here: https://github.com/olikraus/U8g2_Arduino/archive/master.zip Arduino IDE:
PlatformIO:
platformio.ini
(https://docs.platformio.org/en/latest/projectconf/section_env_library.html#lib-deps) should include
lib_deps =
u8g2=https://github.com/olikraus/U8g2_Arduino/archive/master.zip
I tested the updated code. Unfortunately, there are no changes. On Arduino Mega - just a black screen On STM32 - a "snow" image that reacts to the screen content update by blinking its part
I am running out of ideas. Where did you buy that display?
I got it from TELEREX as a product sample. Suspecting the module is damaged, I ordered one more to check how it works. As soon as I have them received it, I will repeat the tests and let you know
I started the display after the modifying the initial sequence and the adding the U8X8_MSG_DISPLAY_DRAW_TILE functionality.
The max frequency of SPI for this controller is around 1MHz
Again, there are some artifacts on the display
#include "u8x8.h"
/*
code copyied from sh1107
ch1120: 160x160 controller from Sino Wealth
*/
static const uint8_t u8x8_d_ch1120_noname_powersave0_seq[] = { U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ch1120_noname_powersave1_seq[] = { U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ch1120_160x160_noname_powersave0_seq[] = { U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ch1120_160x160_noname_powersave1_seq[] = { U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ch1120_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
uint8_t x, c, y;
uint8_t *ptr;
switch (msg) {
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ch1120_64x128_noname_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_64x128_noname_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if (arg_int == 0)
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_noname_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_noname_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if (arg_int == 0) {
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_160x160_noname_powersave0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
} else {
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_160x160_noname_powersave1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081);
u8x8_cad_SendArg(u8x8, arg_int); /* ch1120 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t*) arg_ptr)->x_pos;
y = (((u8x8_tile_t*) arg_ptr)->y_pos);
c = ((u8x8_tile_t*) arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t*) arg_ptr)->tile_ptr; /* data ptr to the tiles */
uint8_t buf[64]; //buffer in bytes for the row = number of tiles*8columns/2 as one byte holds two greyscale pixels
for (uint8_t row = 0; row < 8; row++) {
for (uint8_t col = 0; col < c*8; col++) {
uint8_t *lptr = ptr + col;
uint8_t bit_value = (*lptr >> row) & 0x01;
uint8_t four_bit_value = (bit_value == 1) ? 0xF : 0x0;
buf[col / 2] = (buf[col / 2] << 4) | four_bit_value;
}
u8x8_cad_SendCmd(u8x8, 0x021); /* set column start/stop address */
u8x8_cad_SendArg(u8x8, 0x00);
u8x8_cad_SendArg(u8x8, 0x3F);
u8x8_cad_SendCmd(u8x8, 0x022); /* set row start/stop address */
u8x8_cad_SendArg(u8x8, y * 8 + row);
u8x8_cad_SendArg(u8x8, y * 8 + row + 1);
u8x8_cad_SendData(u8x8, 64, buf);
}
return u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ch1120_160x160_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 60,
/* pre_chip_disable_wait_ns = */ 120,
/* reset_pulse_width_ms = */ 100, /* ch1120: 3 us */
/* post_reset_wait_ms = */ 100, /* sometimes OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 100, /* ch1120: 100ns */
/* sck_pulse_width_ns = */ 100, /* ch1120: 100ns */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* ch1120: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 20,
/* tile_height = */ 20,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 160
};
static const uint8_t u8x8_d_ch1120_128x160_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CAA(0x21, 0x00, 0x3f), /* Set Column Start/End Address of Display RAM, mono mode */
U8X8_CAA(0x22, 0x00, 0x9f), /* Set Row Start/End Address of Display RAM, mono mode */
U8X8_CA(0x0a2, 0x000), /* display start */
U8X8_CA(0x081, 0x08f), /* set contrast control */
U8X8_CA(0x0ac, 0x000), /* mono mode, or 0x003???*/
U8X8_CA(0x020, 0x000), /* addressing mode */
U8X8_C(0x0a0), /* scan direction */
U8X8_C(0x0C8), /* scan direction */
U8X8_CA(0x0a3, 0x001), /* display rotation */
U8X8_C(0x0a4), /* Disable Entire Display OFF/ON */
U8X8_C(0x0a6), /* Set Normal/Reverse Display */
U8X8_CA(0x0a8, 0x07f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x010), /* display offset */
U8X8_CA(0x0d5, 0x01f), /* clock divide ratio and oscillator frequency */
U8X8_CA(0x048, 0x002), /* */
U8X8_CA(0x093, 0x002), /* */
U8X8_CA(0x0d8, 0x001), /* */
U8X8_CA(0x049, 0x006), /* */
U8X8_CA(0x0d9, 0x00f), /* */
U8X8_CA(0x094, 0x01f), /* */
U8X8_CA(0x04b, 0x004), /* */
U8X8_CA(0x0da, 0x000), /* */
U8X8_CA(0x0db, 0x040), /* VSEGM Deselect Level */
U8X8_CA(0x0ad, 0x002), /* */
U8X8_C(0x0aF), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_ch1120_128x160_noname_display_info = {
/* chip_enable_level = */0,
/* chip_disable_level = */1,
/* post_chip_enable_wait_ns = */20,
/* pre_chip_disable_wait_ns = */20,
/* reset_pulse_width_ms = */100, /* ch1120: 3 us */
/* post_reset_wait_ms = */100, /* sometimes OLEDs need much longer setup time */
/* sda_setup_time_ns = */100, /* ch1120: 100ns */
/* sck_pulse_width_ns = */100, /* ch1120: 100ns */
/* sck_clock_hz = */1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */4,
/* data_setup_time_ns = */40,
/* write_pulse_width_ns = */40, /* ch1120: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */16,
/* tile_height = */20,
/* default_x_offset = */0,
/* flipmode_x_offset = */0,
/* pixel_width = */128,
/* pixel_height = */160 };
uint8_t u8x8_d_ch1120_128x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
if (u8x8_d_ch1120_generic(u8x8, msg, arg_int, arg_ptr) != 0)
return 1;
switch (msg) {
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ch1120_128x160_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ch1120_128x160_noname_display_info);
break;
default:
return u8x8_d_ch1120_generic(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
hmmm looks good..., however I am not sure how to help at the moment.
I have encountered an issue with the newer CH1120 driver IC, which seems to be replacing the SH1108. The OLED module looks absolutely the same, has the same pinout (SPI connection) and same resolution (128x160) Despite their similarities, the CH1120 does not function correctly with the existing SH1108 code in the library. I'm using STM32CubeIDE, the display module is connected through the SPI. The module based on SH1108 with the same setup works perfectly
I attempted to modify the existing code:
declared the new function in u8g2.h
void u8g2_Setup_ch1120_128x160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
created the new function in u8g2_d_setup.c
declared the new function in u8x8.h
uint8_t u8x8_d_ch1120_128x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
created the file u8x8_d_ch1120.c (the clone of the u8x8_d_sh1108.c with adopted functions names and modified init_seq and display_info)
the init_seq was modified according to the manufacturers datasheet and rocemmendations:
the display_info was modified according to the manufacturer's datasheet:
Unfortunately, changes I made didn't lead to the working module, only displaying "the snow". But the display reacts for the setting the contrast, rotation and u8g2_SetPowerSave
Please find here the datasheet for the OLED driver IC and for the OLED display based on it WEA160128BWPP3N00000.pdf CH1120 V0.9.pdf