Adafruit-GFX-Library icon indicating copy to clipboard operation
Adafruit-GFX-Library copied to clipboard

Add oled_commandAndArglist() method

Open jordanh opened this issue 4 years ago • 1 comments

Hi Limor, & Adafruit pals.

I recently bought a sample of a 256x64 OLED panel based on the SSD1322 controller from a supplier. I wanted to use the panel in its grayscale mode, so I adapted Limor's SSD1327 driver on a fresh fork.

A difference between the SSD1327 controller and the SSD1322 controller is how the SSD1322 receives commands vs. data. The SSD1327 D/C# pin is always logically false ("command") when commands and arguments are sent. The SSD1322, on the other hand, requires arguments to be sent as ("data") with the D/C# pin high.

Description of changes

The oled_commandList() method does not control the D/C# pin for the SSD1327 controller, so a new method oled_commandAndArglist() has been added. The method asserts D/C# low for each command byte, and high for each argument byte.

It works like this:

  static const uint8_t init_256x64[] {
    2, 0xfd, 0x12,            	        /* unlock */
    1, 0xae,		                /* display off */
    2, 0xb3, 0x91,			/* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec)  */  
    2, 0xca, 0x3f,			/* multiplex ratio 1/64 Duty (0x0F~0x3F) */  
    2, 0xa2, 0x00,			/* display offset, shift mapping ram counter */  
    2, 0xa1, 0x00,			/* display start line */  
    3, 0xa0, 0x06, 0x11,	        /* Set Re-Map / Dual COM Line Mode */
    2, 0xab, 0x01,			/* Enable Internal VDD Regulator */  
    3, 0xb4, 0xa0, 0x05|0xfd,	        /* Display Enhancement A */  
    2, 0xc1, 0x9f,			/* contrast */  
    2, 0xc7, 0x0f,			/* Set Scale Factor of Segment Output Current Control */  
    1, 0xb9,		                /* linear grayscale */
    2, 0xb1, 0xe2,			/* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment */  
    3, 0xd1, 0x82|0x20, 0x20,	        /* Display Enhancement B */  
    2, 0xbb, 0x1f,			/* precharge  voltage */  
    2, 0xb6, 0x08,			/* precharge  period */  
    2, 0xbe, 0x07,			/* vcomh */  
    1, 0xa6,		                /* normal display */
    1, 0xa9		                /* exit partial display */
  };
  
  if (!oled_commandAndArgsList(init_256x64, sizeof(init_256x64))) {
    return false;
  }

See also, full implementation for SSD1322.

Limitations

This introduces two means of specifying list of display commands to the Adafruit_GrayOLED class. I don't love the duplication or how each method implicitly handles the D/C# pin. A better approach might be to modify oled_commandList() to use a similarly specified list of command and args as my oled_commandAndArglist() method and add a bool argument argAsData to define whether or not D/C# is asserted when sending command arguments. For example:

  static const uint8_t init_256x64[] {
    2, 0xfd, 0x12,            	        /* unlock */
    /* ... * /
    3, 0xb4, 0xa0, 0x05|0xfd,	        /* Display Enhancement A */  
    2, 0xc1, 0x9f,			/* contrast */  
     /* ... * / 
    1, 0xa9		                /* exit partial display */
  };
  
  if (!oled_commandList(init_256x64, sizeof(init_256x64), /* argAsData */ true)) {
    return false;
  }

I didn't want to introduce this change to your interface as a few downstream drivers depend on it. If you prefer it, I'd be happy to give PRs against the existing Adafruit drivers that rely on Adafruit_GrayOLED::oled_commandList(). If you want to go that route, just let me know in the comments here and we can coordinate.

jordanh avatar Jan 23 '21 23:01 jordanh

ok to clarify you just need to have the D/C pin inverted right? can you have an optional argument to the existing library function for the DC polarity then?

ladyada avatar Jan 24 '21 00:01 ladyada