SSD1306 128x64 to 64x48 size Oled Display

I've been using the 128x64 oled display that uses the SSD1306 driver and I'd like to try a smaller sized 64X48 one. It looks like defining the smaller size is in the initialization. It might be the line sendcommand(0x2F); //--1/48 duty //was sendcommand(0x3F) for 128X64 sized display but I have to test.

If anyone is using a 64x48 sized display and can help then please let me know.

This is my 128x64 init only code:

static void init_OLED(void)
{
  sendcommand(0xae);		//display off
  sendcommand(0xa6);            //Set Normal Display (default) 
    // Adafruit Init sequence for 128x64 OLED module
    sendcommand(0xAE);             //DISPLAYOFF
    sendcommand(0xD5);            //SETDISPLAYCLOCKDIV
    sendcommand(0x80);            // the suggested ratio 0x80
    sendcommand(0xA8);            //SSD1306_SETMULTIPLEX
    sendcommand(0x2F); //--1/48 duty    //was sendcommand(0x3F) for 128X64
    sendcommand(0xD3);            //SETDISPLAYOFFSET
    sendcommand(0x0);             //no offset
    sendcommand(0x40 | 0x0);      //SETSTARTLINE
    sendcommand(0x8D);            //CHARGEPUMP
    sendcommand(0x14);
    sendcommand(0x20);             //MEMORYMODE
    sendcommand(0x00);             //0x0 act like ks0108
    
    sendcommand(0xA0 | 0x1);      //SEGREMAP   //Rotate screen 180 deg
    //sendcommand(0xA0);
    
    sendcommand(0xC8);            //COMSCANDEC  Rotate screen 180 Deg
    //sendcommand(0xC0);
    
    sendcommand(0xDA);            //0xDA
    sendcommand(0x12);           //COMSCANDEC
    sendcommand(0x81);           //SETCONTRAS
    sendcommand(0xCF);           //
    sendcommand(0xd9);          //SETPRECHARGE 
    sendcommand(0xF1); 
    sendcommand(0xDB);        //SETVCOMDETECT                
    sendcommand(0x40);
    sendcommand(0xA4);        //DISPLAYALLON_RESUME        
    sendcommand(0xA6);        //NORMALDISPLAY             

  clear_display();
  sendcommand(0x2e);            // stop scroll
  //----------------------------REVERSE comments----------------------------//
  //  sendcommand(0xa0);		//seg re-map 0->127(default)
  //  sendcommand(0xa1);		//seg re-map 127->0
  //  sendcommand(0xc8);
  //  delay(1000);
  //----------------------------REVERSE comments----------------------------//
  // sendcommand(0xa7);  //Set Inverse Display  
  // sendcommand(0xae);		//display off
  sendcommand(0x20);            //Set Memory Addressing Mode
  sendcommand(0x00);            //Set Memory Addressing Mode ab Horizontal addressing mode
  //  sendcommand(0x02);         // Set Memory Addressing Mode ab Page addressing mode(RESET)  
  
   setXY(0,0);
  /*
  for(int i=0;i<128*8;i++)     // show 128* 64 Logo
  {
    SendChar(pgm_read_byte(logo+i));
  }
  */
  sendcommand(0xaf);		//display on
}

After looking into it, I see there is a whole lot more to it then just tweaking a line or two in the init file.

hmm... you could use u8glib and modify the SSD1306 128x64 driver:

https://code.google.com/p/u8glib/source/browse/csrc/u8g_dev_ssd1306_128x64.c

First, change WIDTH and HEIGHT to 64 and 48 (lines 39 and 40).
Then update the init sequence. By default this is u8g_dev_ssd1306_128x64_adafruit3_init_seq (line 112).

After this, you should be able to at least see something with the U8GLIB_SSD1306_128x64 constructor.

Oliver

I have simple working test code (attached) for the 128X64 that I'm hoping to modify for the smaller display. Do you have experience with the SSD1306? It looks like the colomn, row values will have to be adjusted. Right now on the smaller display it works but the first few and last characters cut off.

Oled_Test_Code.zip (5.55 KB)

The OLED has a size of 64x48. The controller has a size of 128x64 pixel. The question is, how is the OLED window mapped into the 128x64 RAM are of the controller.
Or: How is the upper left corner of the OLED display mapped onto the RAM of the controller.
This is very specific to the connection between controller and OLED and can have (almost) any mapping. For example if the OLED display is centered in the RAM of the controller, then the upper left corner of the display has the pixel coordinates (32,8).

Usually this is documented in the datasheet for the specific OLED module.

A similar discussion is here: What's the difference between Adafruit SSD1306 and SH1106? - #5 by olikraus - Programming Questions - Arduino Forum

Oliver

Bringing this old thread back up, since I have a similar problem.

Got a 64x48 i2c oled display from ebay, seller wide.hk. Description says it's using the SSD1306 controller, and sure enough, if I feed it with 5v on it's Vcc, the stock Adafruit library for SSD1306_128_64 works, but naturally it can't draw the full 128x64 content.

Here's the thing, according to a datasheet I found at

the oled panel is likely set up to use a portion of the usable controller RAM.
Page 4 of that PDF illustrates that the 64x48 panel is centered on the x axis of the 128 pixels, i.e. shifted 32 pixels, and snapped to the bottom of the y axis, which should mean shifted down 16 pixels.

I tried mucking about with the adafruit library to decrease the size of the internal buffer in the library, but that's not enough, since the library assumes the display has the full 128 pixel width, starting at a corner.

It's possibly easier to tweak u8glib to use that panel efficiently, but I haven't digged into it yet. Olikraus, do you have any insight to this? :slight_smile:

Hi

I think this should not be a big problem with u8glib.
Let me discuss this file:
https://code.google.com/p/u8glib/source/browse/csrc/u8g_dev_ssd1306_128x64.c

  1. Change lines 39 and 40
  2. The sequence in line 182 defines the x-offset, so i guess it should be modified like this:
static const uint8_t u8g_dev_ssd1306_128x64_data_start[] PROGMEM = {
  U8G_ESC_ADR(0),           /* instruction mode */
  U8G_ESC_CS(1),             /* enable chip */
  0x012,                /* set upper 4 bit of the col adr to 32 pixel offset */
  0x000,                /* set lower 4 bit of the col adr to 0  */
  U8G_ESC_END                /* end of sequence */
};
  1. Modify line 230 for the y-offset:
u8g_WriteByte(u8g, dev, 0x0b0 | (pb->p.page+2)); /* select current page (SSD1306), skip first 2 pages (16 rows) */

Oliver

Thanks Oliver, that helps in terms of getting the local address space right, so now pixel 0,0 seems to be where you'd expect.
It does however not make all lines of the display usable; you only get 24 lines to show up if you try to light all the pixels.

Oliver helped me decipher the previously posted datasheet, and if I'm reading it right the
0xDA init sequence should be set to 0x12, resulting in "Alternative COM pin configuration" and "Disable COM Left/Right remap". Further, the 0xC8 init sequence should be sent, resulting in "COM output Scan direction: from COM63 to COM0".
I thought doing this would help with the 24 lines problem, but I'm afraid it doesn't so I'll have to study the datasheet some more it seems. From experimenting I think the display looks best with 0xDA set to 0x02, but I don't think it's 100% right.

Thanks again for helping out Oliver!

Why do you think it is not 100% right? How does it look like at the moment?

Oliver

Hi

Good news: This display will be supported by the upcoming version of U8glib.
Please excause the delay, shipping took some time and then I got busy with the transition of the U8glib project from google code to github.

Oliver

I've written about driving one of these displays here:

http://www.technoblogy.com/show?WNM