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

Winstar WEO012864 with SSD1309 chip #681

Closed
ghost opened this issue Aug 16, 2018 · 36 comments
Closed

Winstar WEO012864 with SSD1309 chip #681

ghost opened this issue Aug 16, 2018 · 36 comments
Labels
Milestone

Comments

@ghost
Copy link

ghost commented Aug 16, 2018

Hello,

Would anyone be able to help me out driving a Winstar WEO012864 display.
datasheet: https://www.texim-europe.com/getfile.ashx?id=113148
I am communicating over SPI with it and I am able to turn the entire display on using the 0xA5 command. The controller I am using is an EFM32GG11.

When I use the following setup:

u8g2_Setup_ssd1309_128x64_noname2_f(&u8g2,  U8G2_R2, u8x8_byte_4wire_hw_spi_EFM32, u8g2_gpio_and_delay_EFM32);
u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this
u8g2_SetPowerSave(&u8g2, 0); // wake up display
	while(1)
	{
		  u8g2_ClearBuffer(&u8g2);
		  u8g2_SetFont(&u8g2,u8g_font_4x6);
		  u8g2_DrawStr(&u8g2,0,5,"HELLO WORLD!");
		  u8g2_SendBuffer(&u8g2);
		  Delay(100);
	}

Text is drawn on the top portion (bottom for the viewer because it is flipped with the FPC on the other side of the PCB) of the display but it is "scrolling" backward from right to left.
Also the rest of the displays buffers aren't filled.

20180816_163955

I have implemented:

uint8_t u8g2_gpio_and_delay_EFM32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  switch(msg)
  {
    case U8X8_MSG_GPIO_AND_DELAY_INIT:	// called once during init phase of u8g2/u8x8
    	// Done in initDevice.c for now
      break;							// can be used to setup pins
    case U8X8_MSG_DELAY_NANO:			// delay arg_int * 1 nano second --> Do nothing not even NOP as our processor is only running at 48MHz
      break;
    case U8X8_MSG_DELAY_100NANO:		// delay arg_int * 100 nano seconds --> 0,0000001s/,000000021s = +/- 5
		for (uint16_t n = 0; n < 5; n++)
		{
			__NOP();
		}
      break;
    case U8X8_MSG_DELAY_10MICRO:		// delay arg_int * 10 micro seconds --> 0,000010s/(1/48MHz) = +/- 476
		for (uint16_t n = 0; n < 476; n++)
		{
			__NOP();
		}
      break;
    case U8X8_MSG_DELAY_MILLI:			// delay arg_int * 1 milli second
    	Delay(arg_int);
      break;
    case U8X8_MSG_DELAY_I2C:				// arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
      break;							// arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
    case U8X8_MSG_GPIO_D0:				// D0 or SPI clock pin: Output level in arg_int
    	if(arg_int)GPIO_PinOutSet(DISPLAY_USART3_CLK);
    	else GPIO_PinOutClear(DISPLAY_USART3_CLK);
    //case U8X8_MSG_GPIO_SPI_CLOCK:
      break;
    case U8X8_MSG_GPIO_D1:				// D1 or SPI data pin: Output level in arg_int
    	if(arg_int)GPIO_PinOutSet(DISPLAY_USART3_TX);
    	else GPIO_PinOutClear(DISPLAY_USART3_TX);
    //case U8X8_MSG_GPIO_SPI_DATA:
      break;

// NOT USED
//    case U8X8_MSG_GPIO_D2:				// D2 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_D3:				// D3 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_D4:				// D4 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_D5:				// D5 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_D6:				// D6 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_D7:				// D7 pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_E:				// E/WR pin: Output level in arg_int
//      break;


    case U8X8_MSG_GPIO_CS:				// CS (chip select) pin: Output level in arg_int
    	if(arg_int)GPIO_PinOutSet(DISPLAY_USART3_CS);
    	else GPIO_PinOutClear(DISPLAY_USART3_CS);
      break;
    case U8X8_MSG_GPIO_DC:				// DC (data/cmd, A0, register select) pin: Output level in arg_int
    	if(arg_int)GPIO_PinOutSet(DISPLAY_DC);
    	else GPIO_PinOutClear(DISPLAY_DC);
      break;
    case U8X8_MSG_GPIO_RESET:			// Reset pin: Output level in arg_int
    	if(arg_int)GPIO_PinOutSet(DISPLAY_RESET);
    	else GPIO_PinOutClear(DISPLAY_RESET);
      break;

// NOT USED
//    case U8X8_MSG_GPIO_CS1:				// CS1 (chip select) pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_CS2:				// CS2 (chip select) pin: Output level in arg_int
//      break;
//    case U8X8_MSG_GPIO_I2C_CLOCK:		// arg_int=0: Output low at I2C clock pin
//      break;							// arg_int=1: Input dir with pullup high for I2C clock pin
//    case U8X8_MSG_GPIO_I2C_DATA:			// arg_int=0: Output low at I2C data pin
//      break;							// arg_int=1: Input dir with pullup high for I2C data pin
//    case U8X8_MSG_GPIO_MENU_SELECT:
//      u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
//      break;
//    case U8X8_MSG_GPIO_MENU_NEXT:
//      u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
//      break;
//    case U8X8_MSG_GPIO_MENU_PREV:
//      u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
//      break;
//    case U8X8_MSG_GPIO_MENU_HOME:
//      u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
//      break;

    default:
      u8x8_SetGPIOResult(u8x8, 1);			// default return value
      break;
  }
  return 1;
}

uint8_t u8x8_byte_4wire_hw_spi_EFM32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t 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--;
      	  	while(!(USART_DISPLAY->IF & USART_IF_TXBL)); // blocking wait
      		USART_Tx(USART_DISPLAY, b);
        }
      break;

    case U8X8_MSG_BYTE_INIT:
      /* disable chipselect */
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
      /* no wait required here */

      /* for SPI: setup correct level of the clock signal */
      u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
      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;
}

Am I missing something? Any help is appreciated!

Kind regards,
Giovanni.

@ghost
Copy link
Author

ghost commented Aug 16, 2018

Note, I have just tried switching to u8g2_Setup_ssd1306_128x64_noname_f (as I read somewhere they are almost compatible), now I see the single line not only moving backward, but also up on the screen.

@olikraus
Copy link
Owner

Difficult if this is not an Arduino environment. Yet USARTTx looks strange to me.

@ghost
Copy link
Author

ghost commented Aug 17, 2018

@olikraus Actually USART_Tx simply sends out the bytes out via HW SPI.
And I am actually seeing the display respond to commands. So I think that portion is working.
It is as if there is some problem with way the image is created.
The moving across the screen happens every time I update the screen (even though it should draw exactly the same data at the same location). And If I use the SSD1309 setup it only uses a couple of the top lines but nothing else.

Is there some buffer offsets that differ per chip/setup? What are the differences between the different noname1 noname2 setups?

@olikraus
Copy link
Owner

I didn't saw the picture. At least you see something. I don't have access to all of my resources at the moment. Maybe your display requires a complete different setup.

Difference between noname1 and 2 is a different setup, but I can't verify this at the moment.

@ghost
Copy link
Author

ghost commented Aug 17, 2018

@olikraus So my winstar display uses a SSD1309 display, but I saw a definition for another winstar display that uses the SH1106.

If I replace

u8g2_Setup_ssd1309_128x64_noname2_f(&u8g2, U8G2_R2, u8x8_byte_4wire_hw_spi_EFM32, u8g2_gpio_and_delay_EFM32);

by

u8g2_Setup_sh1106_128x64_winstar_f(&u8g2, U8G2_R2, u8x8_byte_4wire_hw_spi_EFM32, u8g2_gpio_and_delay_EFM32);

I get the exact same lines that are working, but 180° flipped. And still the unwanted scrolling backward with every update. I'm guessing there's something wrong with some offsets?
(Note that changing U8G2_R2 changes nothing with regards to the lines that work.)

The datasheet of the display isn't great. (cfr. the URL in the first post.)
I asked the manufacturer for demo-code, but haven't received anything yet.

@olikraus
Copy link
Owner

Maybe you could also check SSD1306 drivers.

@ghost
Copy link
Author

ghost commented Aug 17, 2018

@olikraus

u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R2, u8x8_byte_4wire_hw_spi_EFM32, u8g2_gpio_and_delay_EFM32);

Gives me something like this (animated gif):
20180817_095315

Note that the movement happens everytime I redraw the screen.

@olikraus
Copy link
Owner

Also Strange. As I said, I can't look closer at the moment.

@ghost
Copy link
Author

ghost commented Aug 20, 2018

Still not fully working but I have an update.

Next to the above I have modified inside u8x8_d_ssd1309.c:

    
  U8X8_START_TRANSFER(),        	/* enable chip, delay is part of the transfer start */
  U8X8_C(0x0ae),		                 /* display off */
  U8X8_CA(0x020, 0x000),		/* Set memory addressing mode */
  U8X8_CAA(0x022,0, 7),		/* Set page address */
  U8X8_CAA(0x021,0, 127),		/* Set column address */

  U8X8_CA(0x081, 0x080), 		/* [2] set contrast control for BANK0 */
  U8X8_C(0x040),		                /* set display start line to 0 */
  U8X8_C(0x0a0),				/* segment remap a0/a1 =>0xa0:column addr. 0 is mapped to SEG0 */
  U8X8_C(0x0a4),				/* output ram to display */
  U8X8_C(0x0a6),				/* none inverted normal display mode */
  U8X8_CA(0x0a8, 0x03f),		/* multiplex ratio 63 */
  U8X8_CA(0x0ad, 0x08e),		/* master configuration */
  U8X8_C(0x0C8),				/* Set COM Output Scan Direction =>0xc0:scan from COM0 to 
                                                              COM63, 0xc8:scan from COM63 to COM0*/
  U8X8_CA(0x0d3, 0x000),		/* Display offset */
  U8X8_CA(0x0d5, 0x0f0),		/* Set Display Clock Divid Ratio/Oscillator Frequency */
  U8X8_CA(0x0d8, 0x005),		/* Set Area Color Mode ON/OFF & Low Power Display Mode, 
                                                              0x05:monochrome mode and low power display mode*/
  U8X8_CA(0x0d9, 0x0f1), 		/* [2] pre-charge period 0x022/f1*/
  U8X8_CA(0x0da, 0x012), 		/* Set COM Pins Hardware Configuration */
  U8X8_CA(0x0db, 0x040), 		/* vcomh deselect level */
  U8X8_C(0x02e),				/* Deactivate scroll */
  //U8X8_C(0x0af),		                /* display on */
  U8X8_END_TRANSFER(),             	/* disable chip */
  U8X8_END()             			/* end of sequence */
};

Drawing the following:

u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2,u8g_font_6x12);
u8g2_DrawStr(&u8g2,2,12,"HELLO WORLD!");
u8g2_DrawStr(&u8g2,2,26,"FROM GIOVANNI");
u8g2_DrawStr(&u8g2,2,40,"TO U8G2 LIB");
u8g2_DrawHLine(&u8g2,0,0,128);
u8g2_DrawVLine(&u8g2,0,0,64);
u8g2_SendBuffer(&u8g2);

Gives us:

20180820_140644

@ghost
Copy link
Author

ghost commented Aug 20, 2018

I received following example program from the manufacturer:
WEO012864_SPI.c.zip

@ghost
Copy link
Author

ghost commented Aug 20, 2018

@olikraus Flipped the display, Now we can see that a block that is in the bottom right should be in the top left.

20180820_144903

@ghost
Copy link
Author

ghost commented Aug 20, 2018

@olikraus Because I wanted to be sure that all setup for the display was performed well, I wrote following test code to test auto-increment of the indexes:

 u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
	u8g2_SetPowerSave(&u8g2, 0); // wake up display
    u8x8_cad_StartTransfer((u8x8_t*)&u8g2);
	u8x8_cad_SendCmd((u8x8_t*)&u8g2, 0xA5);// Everything on, without using RAM
	u8x8_cad_EndTransfer((u8x8_t*)&u8g2);
	Delay(1000);
    u8x8_cad_StartTransfer((u8x8_t*)&u8g2);
	u8x8_cad_SendCmd((u8x8_t*)&u8g2, 0xA4);// Back to RAM
	u8x8_cad_EndTransfer((u8x8_t*)&u8g2);
	while(1)
	{
	for(int j = 0; j < 8; j++)
	{
	for(int k = 0; k < 128; k++)
	{
    u8x8_cad_StartTransfer((u8x8_t*)&u8g2);
    uint8_t testbuffer[]={0xFF};
	u8x8_cad_SendData((u8x8_t*)&u8g2, 1,testbuffer);
	u8x8_cad_EndTransfer((u8x8_t*)&u8g2);
	Delay(1);
	};
	}
	for(int j = 0; j < 8; j++)
	{
	for(int k = 0; k < 128; k++)
	{
    u8x8_cad_StartTransfer((u8x8_t*)&u8g2);
    uint8_t testbuffer[]={0x00};
	u8x8_cad_SendData((u8x8_t*)&u8g2, 1,testbuffer);
	u8x8_cad_EndTransfer((u8x8_t*)&u8g2);
	Delay(1);
	};
	}
	}

Result is as expected, 8 pixels are written with every iteration of the for loop. So the Init should be ok.

20180820_163547

@olikraus
Copy link
Owner

olikraus commented Aug 21, 2018

ok, i think the SSD1309 implementation is broken.
I will create a fix soon.

@olikraus olikraus added the bug label Aug 21, 2018
@olikraus olikraus added this to the 2.23 milestone Aug 21, 2018
olikraus added a commit that referenced this issue Aug 21, 2018
@olikraus
Copy link
Owner

I have created beta 2.23.17. Will it help?

You can download the latest U8g2 beta release from here: https://github.com/olikraus/U8g2_Arduino/archive/master.zip

  1. Remove the existing U8g2_Arduino library (https://stackoverflow.com/questions/16752806/how-do-i-remove-a-library-from-the-arduino-environment)
  2. Install the U8g2_Arduino Zip file via Arduino IDE, add zip library menu (https://www.arduino.cc/en/Guide/Libraries).

@ghost
Copy link
Author

ghost commented Aug 22, 2018

@olikraus I will test later today!

@ghost
Copy link
Author

ghost commented Aug 22, 2018

@olikraus I managed to get everything working!

20180822_134315

I actually needed to comment 3 lines from static uint8_t u8x8_d_ssd1309_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)

Also I needed the init code that I already wrote here

static uint8_t u8x8_d_ssd1309_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t x, c;
  uint8_t *ptr;
  switch(msg)
  {
    case U8X8_MSG_DISPLAY_DRAW_TILE:
      u8x8_cad_StartTransfer(u8x8);
      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
      x *= 8;
      x += u8x8->x_offset;
    
      //u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
      //u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
      //u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)   );

    
      do
      {
	c = ((u8x8_tile_t *)arg_ptr)->cnt;
	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
	/*
	do
	{
	  u8x8_cad_SendData(u8x8, 8, ptr);
	  ptr += 8;
	  c--;
	} while( c > 0 );
	*/
	arg_int--;
      } while( arg_int > 0 );
      
      u8x8_cad_EndTransfer(u8x8);
      break;
    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
      if ( arg_int == 0 )
	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave0_seq);
      else
	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave1_seq);
      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 );	/* ssd1309 has range from 0 to 255 */
      u8x8_cad_EndTransfer(u8x8);
      break;
#endif
    default:
      return 0;
  }
  return 1;
}

Thanks for the assistance you gave! Much appreciated! I hope this thread will help future people using a similar winstar display.

@olikraus
Copy link
Owner

olikraus commented Aug 22, 2018

I am confused about commenting out the curser commands. It may work, but it might be unreliable. Did you test any animation? Like the GraphicsTest.ino?

Additionally, this will fully break the u8x8 mode.

@ghost
Copy link
Author

ghost commented Aug 23, 2018

Well actually, the curser commands are "printed" on the display, causing an offset to occur.
I think I know why. I have set my device in horizontal addressing mode instead of page addressing mode. I could not get it to work with the page addressing mode.

@ghost
Copy link
Author

ghost commented Aug 23, 2018

@olikraus In page mode, with your init code, it is like there's only one page working.

@olikraus
Copy link
Owner

I have ordered a SSD1309 display for further testing.

@ghost
Copy link
Author

ghost commented Aug 23, 2018

@olikraus Investigating further it seems that on my platform, after initial config, once I have written something to the display, command mode is not working anymore and all commands are interpreted as data. Even though the toggling of the DC line is called. Still investigating...

@ghost
Copy link
Author

ghost commented Aug 23, 2018

It explains why horizontalmode was working because that one does not need commands afterwards.

@olikraus
Copy link
Owner

True ... Do we need to enable page mode again?

@ghost
Copy link
Author

ghost commented Aug 23, 2018

@olikraus Traced it back to a badly driven D/C line. Fixed it in hardware and page mode is working now. Next: I will test the old init code that you had originally.

Hope you didn't go through great expense ordering a SSD1309.

@ghost
Copy link
Author

ghost commented Aug 23, 2018

@olikraus Ok, original init code is working as well now. Ok, so bottomline, a hardware error just cost me a lot of time. Funny thing is, I could actually see the DC line toggle on my measurement point. Just before the FPC connector. Now I feel guilty taking up your time! Next time I'm in Germany, I should buy you a drink!

@olikraus
Copy link
Owner

Glad you solved the problem :)

@olikraus olikraus removed the bug label Aug 24, 2018
olikraus added a commit that referenced this issue Jan 23, 2019
@azd1988
Copy link

azd1988 commented Jan 6, 2020

Hi @olikraus ,
Im really stuck please help me , Im using an OLED similar to yours (64X128 from winstar WEO012864AWAP3N00000) I want to control it with SPI or I2C on MCU EFM32GG11.
Thanks in advance.

@olikraus
Copy link
Owner

olikraus commented Jan 6, 2020

Any link to the datasheet?
How did you connect the OLED?
Which constructor did you use?

@azd1988
Copy link

azd1988 commented Jan 6, 2020

https://www.telerex-europe.com/content/files/pdfs/productPdfs/WS/OLED/WEO012864AWAP3N00000.pdf
I used I2C through Arduino .
the constructor is Wistar company

@olikraus
Copy link
Owner

olikraus commented Jan 6, 2020

the constructor is Wistar company

I mean, which U8g2 C++ construcutor did you uncomment?

What is MCU EFM32GG11?
And again: How did you connect the OLED to your uC?

@azd1988
Copy link

azd1988 commented Jan 6, 2020

TBH, I did not use U8g2 library. I used adafruit_ssd1306 and adafruit_GFX (my OLED has 1309 driver which is compatible with 1306).
MCU EFM32GG11 is a developement board based on microcontroller giant gecko EFM32GG11. and I did not connect it yet MCU , I have just used ARDUINo

@azd1988
Copy link

azd1988 commented Jan 6, 2020

#681 (comment)
@ghost

@olikraus
Copy link
Owner

olikraus commented Jan 6, 2020

OLED has 1309 driver which is compatible with 1306

I think: 1309 driver is NOT compatible with 1306

MCU EFM32GG11 is a developement board based on microcontroller giant gecko EFM32GG11. and I did not connect it yet MCU , I have just used ARDUINo

hm, so how can I help here?

@azd1988
Copy link

azd1988 commented Jan 6, 2020

sorry, I thought you got C codes that control 1309-driver through EFM32GG11,
May I ask @ghost?

@olikraus
Copy link
Owner

olikraus commented Jan 6, 2020

May I ask @ghost?

sure, but who is ghost?

@olikraus
Copy link
Owner

olikraus commented Jan 6, 2020

Oh, I think the original poster got deleted from github and is now called "ghost".

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

No branches or pull requests

2 participants