Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

t6963 f Data Hold Time #2427

Open
carlk3 opened this issue Apr 16, 2024 · 6 comments
Open

t6963 f Data Hold Time #2427

carlk3 opened this issue Apr 16, 2024 · 6 comments

Comments

@carlk3
Copy link

carlk3 commented Apr 16, 2024

Thank you for providing an excellent library!

We're doing some extreme testing with a Newhaven NHD-240128WG-BTMI-VZ# LCD, using a 10' long shielded 20-conductor cable to connect the display. It worked well when we were using a 200 mm ribbon cable but we got dropped pixels with the 10' cable. (We're not really going to use a 10' cable in production but we are trying to build in some margin for robustness.) We found that the rise time of the E/WR signal was so long that the data lines were changing before getting latched with E/WR. We were able to get it to work well by adding a Data Hold delay in csrc/u8x8_byte.c:

--- a/csrc/u8x8_byte.c
+++ b/csrc/u8x8_byte.c
@@ -35,6 +35,7 @@
 */
 
 #include "u8x8.h"
+#include "micros.h"
 
 uint8_t u8x8_byte_SetDC(u8x8_t *u8x8, uint8_t dc)
 {
@@ -237,6 +238,8 @@ uint8_t u8x8_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
        u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
        u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
        u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
+
+       delay_us(1); // Data hold time
       }
       break;

This is what it looks like now:
scope_82

Note: we are using a 3.3 V STM32 MCU, and to do the level shifting to the 5 V Newhaven we are using Open Collector GPIO outputs with 5 k Ω pull-ups. The data lines suffer the same extended rise times as E/WR so data transitions from 0 to 1 were OK, but transitions from 1 to 0 are driven low very quickly.

I don't like to modify your library, and I'm wondering if there is a better way to do this.

@olikraus
Copy link
Owner

modifing u8g2 should be fine.
As an alternative, you could replace the byte procedure, like for example here: https://github.com/olikraus/u8g2/blob/master/sys/arduino/u8g2_page_buffer/I2CLCDBoard/I2CLCDBoard.ino

@carlk3
Copy link
Author

carlk3 commented Apr 27, 2024

As an alternative, you could replace the byte procedure...

Thanks. That looks like a good method. That way I won't lose track of it in my source code control system.

@olikraus
Copy link
Owner

Not tested, but this should replicate the same default behavior.
With this setup you could simply write your own optimized byte procedure.

U8G2 u8g2;              // create a plain U8g2 object

uint8_t u8x8_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t i, b;
  uint8_t *data;
 
  switch(msg)
  {
    case U8X8_MSG_BYTE_SEND:
      data = (uint8_t *)arg_ptr;
      while( arg_int > 0 )
      {
	b = *data;
	data++;
	arg_int--;
	for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
	{
	  u8x8_gpio_call(u8x8, i, b&1);
	  b >>= 1;
	}    
	
	u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
	u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
	u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
	u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
      }
      break;
      
    case U8X8_MSG_BYTE_INIT:
      /* disable chipselect */
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);    
      /* ensure that the enable signal is high */
      u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
      break;
    case U8X8_MSG_BYTE_SET_DC:
      u8x8_gpio_SetDC(u8x8, arg_int);
      break;
    case U8X8_MSG_BYTE_START_TRANSFER:
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);  
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
      break;
    case U8X8_MSG_BYTE_END_TRANSFER:
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
      break;
    default:
      return 0;
  }
  return 1;
}


void setup(void) 
{
  u8g2_Setup_t6963_240x128_2(u8g2.getU8g2(), U8G2_R0, u8x8_byte_8bit_8080mode, u8x8_gpio_and_delay_arduino);
}

@olikraus
Copy link
Owner

Setup procedures are described here: https://github.com/olikraus/u8g2/wiki/u8g2setupc

@olikraus
Copy link
Owner

Inside Arduino Env you could use void u8x8_SetPin_8Bit_8080(u8x8_t *u8x8, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t wr, uint8_t cs, uint8_t dc, uint8_t reset); to assign the pins.

@carlk3
Copy link
Author

carlk3 commented Apr 27, 2024

Thanks. I implemented the private byte procedure and it works fine. I'm actually using the STM32CubeIDE, not Arduino.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants