diff --git a/csrc/u8x8_byte.c b/csrc/u8x8_byte.c index 8f6467d4..c90a3db8 100644 --- a/csrc/u8x8_byte.c +++ b/csrc/u8x8_byte.c @@ -437,6 +437,7 @@ uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ case U8X8_MSG_BYTE_START_TRANSFER: /* cs lines are not supported for the SED1520/SBN1661 */ /* instead, this will select the E1 or E2 line */ + /* arg_int is set by u8x8_d_sbn1661_122x32() function */ enable_pin = U8X8_MSG_GPIO_E; if ( arg_int != 0 ) enable_pin = U8X8_MSG_GPIO_CS; diff --git a/sys/arduino/u8g2_full_buffer/HelloWorld/HelloWorld.ino b/sys/arduino/u8g2_full_buffer/HelloWorld/HelloWorld.ino index e95a19b6..57032b25 100644 --- a/sys/arduino/u8g2_full_buffer/HelloWorld/HelloWorld.ino +++ b/sys/arduino/u8g2_full_buffer/HelloWorld/HelloWorld.ino @@ -293,7 +293,7 @@ //U8G2_LC7981_240X128_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND //U8G2_LC7981_240X64_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND //U8G2_LC7981_128X128_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND -//U8G2_SED1520_122X32_F u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*dc=*/ A0, /*e1=*/ A3, /*e2=*/ A2, /* reset=*/ A4); // Set R/W to low! +U8G2_SED1520_122X32_F u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*dc=*/ A0, /*e1=*/ A3, /*e2=*/ A2, /* reset=*/ A4); // Set R/W to low! //U8G2_T6963_240X128_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable/wr=*/ 17, /*cs/ce=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FS0 and FS1 with GND //U8G2_T6963_256X64_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable/wr=*/ 17, /*cs/ce=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FS0 and FS1 with GND //U8G2_T6963_160X80_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable/wr=*/ 17, /*cs/ce=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FS0 and FS1 with GND diff --git a/sys/arduino/u8g2_page_buffer/I2CLCDBoard/I2CLCDBoard.ino b/sys/arduino/u8g2_page_buffer/I2CLCDBoard/I2CLCDBoard.ino index e2d66d51..18275a2c 100644 --- a/sys/arduino/u8g2_page_buffer/I2CLCDBoard/I2CLCDBoard.ino +++ b/sys/arduino/u8g2_page_buffer/I2CLCDBoard/I2CLCDBoard.ino @@ -40,9 +40,9 @@ /* - Example for the I2C GFX Board https://github.com/olikraus/u8g2/issues/2191 + Example for the I2C LCD GFX Board https://github.com/olikraus/u8g2/issues/2191 Required updates for T6963 and LC7981 : - 1. Update write strobe and chip select signals in "u8x8_byte_i2c_lcd_board()" + 1. Update write strobe and chip select signals in "u8x8_byte_i2c_lcd_gfx_board_t6963_8080()" 2. Update the setup procedure in "setup()" @@ -78,7 +78,7 @@ only update operation will be u8x8_set_ctrl_bit(u8x8, 0, 1); typically the second argument will be one of the I2C_LCD_xxx macros - reusing the i2c_started member, which is not used by the i2c lcd board software (i2c_started is only used by sw emulated i2c) + reusing the "i2c_started" member variable, which is not used by the i2c lcd board software (i2c_started is only used by sw emulated i2c) */ void u8x8_set_ctrl_bit(u8x8_t *u8x8, uint8_t bit, uint8_t is_set) U8X8_NOINLINE; void u8x8_set_ctrl_bit(u8x8_t *u8x8, uint8_t bit, uint8_t is_set) @@ -96,7 +96,7 @@ void u8x8_set_ctrl_bit(u8x8_t *u8x8, uint8_t bit, uint8_t is_set) /* The new gpio&delay procedure extents the existing arduino procedure and adds proper reset handling */ -uint8_t u8x8_gpio_and_delay_i2c_lcd_board(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, U8X8_UNUSED void *arg_ptr) +uint8_t u8x8_gpio_and_delay_i2c_lcd_gfx_board(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, U8X8_UNUSED void *arg_ptr) { uint8_t i; switch(msg) @@ -105,18 +105,21 @@ uint8_t u8x8_gpio_and_delay_i2c_lcd_board(u8x8_t *u8x8, uint8_t msg, uint8_t arg u8x8_set_ctrl_bit(u8x8, I2C_LCD_RESET, arg_int); return 1; case U8X8_MSG_GPIO_AND_DELAY_INIT: - u8x8->i2c_started = I2C_LCD_CS|I2C_LCD_RD|I2C_LCD_RESET|I2C_LCD_LED_DEFAULT; // reused i2c_started to store the gpio state - u8x8_set_ctrl_bit(u8x8, 0, 1); // just transmit the control byte + u8x8->i2c_started = I2C_LCD_CS|I2C_LCD_RD|I2C_LCD_RESET|I2C_LCD_LED_DEFAULT; // assign default value for ctrl byte, reuse "i2c_started" member variable to store the gpio state + u8x8_set_ctrl_bit(u8x8, 0, 1); // just transmit the control byte (which is stored in "i2c_started" member variable) return 1; } return u8x8_gpio_and_delay_arduino(u8x8, msg, arg_int, arg_ptr); } /* - This is an example byte level procedure for my T6963 board. - Chips select and write strobe signals may differ. + This is an example byte level procedure for a T6963 board. + This procedure will assume, that the T6963 is configured in 8080 mode. + Probably the same procedure can be also used for LC7981 displays. + + In general chip select and write strobe signals may differ and need to be checked. */ -uint8_t u8x8_byte_i2c_lcd_board(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +uint8_t u8x8_byte_i2c_lcd_gfx_board_t6963_8080(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { /* usually only the following two varibables need to be modified */ uint8_t write_strobe = I2C_LCD_RW; /* T6963 in 8080mode */ @@ -171,18 +174,103 @@ uint8_t u8x8_byte_i2c_lcd_board(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void } +/* + This is an example byte level procedure for SED1520 / SBN1661 displays. + The display needs to be configured in 6800 mode. + + In general chip select and write strobe signals may differ and need to be checked. +*/ +uint8_t u8x8_byte_i2c_lcd_gfx_board_sed1520_6800(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t chip_select = I2C_LCD_CS; + uint8_t *data; + static uint8_t enable_pin = I2C_LCD_E; // the enable pin may differ. The current enable pin number is stored here + + switch(msg) + { + case U8X8_MSG_BYTE_SEND: + data = (uint8_t *)arg_ptr; + while( arg_int > 0 ) + { + Wire.beginTransmission(I2C_LCD_DATA_ADR); + Wire.write(*data); + Wire.endTransmission(); + + data++; + arg_int--; + + + // Assumption: u8x8_set_ctrl_bit() will be slow enough, so that no extra delay is required + + //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns); + u8x8_set_ctrl_bit(u8x8, enable_pin, 0); + //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 200); + //u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns); + u8x8_set_ctrl_bit(u8x8, enable_pin, 1); + + + } + break; + + case U8X8_MSG_BYTE_INIT: + Wire.begin(); + Wire.setClock(400000); // Assumption: PCF8574A supports fast I2C mode + + /* 6800 mode: Permanently assign R/W to GND */ + u8x8_set_ctrl_bit(u8x8, I2C_LCD_RW, 0); // in 6800 mode, the R/W can 0 all the time (write mode only) + + /* chipselect */ + u8x8_set_ctrl_bit(u8x8, I2C_LCD_CS, 0); // there is no CS for the SED1520... but still, we apply a default value here + + /* ensure that the enable signal is high */ + u8x8_set_ctrl_bit(u8x8, I2C_LCD_E, 0); // clear E1 + u8x8_set_ctrl_bit(u8x8, I2C_LCD_E2, 0); // clear E2 + enable_pin = I2C_LCD_E; // assign E1 as initial enable signal + break; + + case U8X8_MSG_BYTE_SET_DC: + u8x8_set_ctrl_bit(u8x8, I2C_LCD_CD, arg_int); // command/data data/command + break; + + case U8X8_MSG_BYTE_START_TRANSFER: + /* arg_int is set by u8x8_d_sbn1661_122x32() function (which is also used by sed1520) */ + enable_pin = I2C_LCD_E; + if ( arg_int != 0 ) // the CAD procedure will tell, which enable signal to use + enable_pin = I2C_LCD_E2; + break; + + case U8X8_MSG_BYTE_END_TRANSFER: + break; + + default: + return 0; + } + return 1; +} + U8G2 u8g2; // create a plain U8g2 object -void setup(void) { +void setup(void) +{ /* Do a manual update of the plain U8g2 object with the C API for the display. - Use a special byte function, which includes the support for the I2C GFX boad. + Use a special byte function, which includes the support for the I2C LCD GFX boad. The C init functions are listed here: https://github.com/olikraus/u8g2/wiki/u8g2setupc Just replace the function name accordingly. + + Note: + For T6963 / LC7981 displays, use the "u8x8_byte_i2c_lcd_gfx_board_t6963_8080" callback function. + For SBN1661 / SED1520 use the "u8x8_byte_i2c_lcd_gfx_board_sed1520_6800" callback function. + + */ + // u8g2_Setup_t6963_240x128_2(u8g2.getU8g2(), U8G2_R0, u8x8_byte_i2c_lcd_gfx_board_t6963_8080, u8x8_gpio_and_delay_i2c_lcd_gfx_board); + u8g2_Setup_sed1520_122x32_2(u8g2.getU8g2(), U8G2_R0, u8x8_byte_i2c_lcd_gfx_board_sed1520_6800, u8x8_gpio_and_delay_i2c_lcd_gfx_board); + + /* + After providing the callback function, start the communication with the display by using u8g2.begin() */ - u8g2_Setup_t6963_240x128_2(u8g2.getU8g2(), U8G2_R0, u8x8_byte_i2c_lcd_board, u8x8_gpio_and_delay_i2c_lcd_board); u8g2.begin(); } @@ -190,14 +278,16 @@ uint8_t x = 0; long t = 0; long tt = 0; -void loop(void) { +void loop(void) +{ t = millis(); u8g2.firstPage(); - do { - u8g2.setFont(u8g2_font_ncenB24_tr); - u8g2.drawStr(x*2,32,"Hello World!"); - u8g2.drawStr(x*2,64,"U8g2"); - u8g2.setCursor(x*2, 96); + do + { + u8g2.setFont(u8g2_font_ncenB18_tr); + u8g2.drawStr(x*2,19,"Hello World!"); + u8g2.setFont(u8g2_font_ncenB12_tr); + u8g2.setCursor(x*2, 32); u8g2.print(tt, DEC); } while ( u8g2.nextPage() ); x++;