Go Down

Topic: SSD1327 128x128 I2C library (Read 871 times) previous topic - next topic

Buleste

Are there any small libraries for this screen other than the u8g2 libraries?

Preferably as small as possible.

Buleste

Okay. I've decided to come back to this and I'm trying to write a small library based on a SSD1306 basic library.

I've been studying the datasheets of both and looking around for information on the SSD1327 and I have a library that at least displays something, it's garbage but it's a start.

I'm thinking the issues are with setting the page address and the columns which of course then messes up everything else.

Would anyone like to give me a hand so that it will be possible to have a 128x128 OLED display working on Maybe a Uno or Mega?

I've had to edit out the font due to post size. I'll add it in another reply.

Code: [Select]
#define OLED_address   0x3C //0x3C or 0x3D

   

 
    // Used to send commands to the display.
    static void sendcommand(unsigned char com)
    {
    Wire.beginTransmission(OLED_address); //begin transmitting
    Wire.write(0x80); //command mode
    Wire.write(com);
    Wire.endTransmission(); // stop transmitting
    }
    
    // Actually this sends a byte, not a char to draw in the display.
    // Display's chars uses 8 byte font the small ones and 96 bytes
    // for the big number font.
    static void SendByte(unsigned char data)
    {
    Wire.beginTransmission(OLED_address); // begin transmitting
    Wire.write(0x40);//data mode
    Wire.write(data);
    Wire.endTransmission(); // stop transmitting
    }
    
    // Prints a display char (not just a byte)
    // being multiples of 8. This means we have 16 COLS (0-15)
    // and 8 ROWS (0-7).
    static void sendChar(unsigned char data)
    {
    Wire.beginTransmission(OLED_address); // begin transmitting
    Wire.write(0x40);//data mode
    for(int i=0;i<8;i++)
    Wire.write(pgm_read_byte(myFont[data-0x20]+i));
    Wire.endTransmission(); // stop transmitting
    }
    
    // Set the cursor position in a 16 COL * 2 ROW map.
    static void setXY(unsigned char col,unsigned char row)
    {
    sendcommand(0xa0+row); //set page address
    
    sendcommand(0x00+(8*col&0x15)); //set low col address
        
    sendcommand(0x10+((8*col>>4)&0x15)); //set high col address
    }
    
    // Prints a string regardless the cursor position.
    static void sendStr(unsigned char *string)
    {
    unsigned char i=0;
    while(*string)
    {
    for(i=0;i<8;i++)
    {
    SendByte(pgm_read_byte(myFont[*string-0x20]+i));
    }
    *string++;
    }
    }
    
    // Prints a string in coordinates X Y, being multiples of 8.
    // This means we have 16 COLS (0-15) and 8 ROWS (0-7).
    static void sendStrXY( char *string, int X, int Y)
    {
    setXY(X,Y);
    unsigned char i=0;
    while(*string)
    {
    for(i=0;i<8;i++)
    {
    SendByte(pgm_read_byte(myFont[*string-0x20]+i));
    }
    *string++;
    }
    }
    
// Resets display depending on the actual mode.
static void reset_display(void)
{
  displayOff();
  clear_display();

  
  displayOn();
}



// Turns display on.
void displayOn(void)
{
    sendcommand(0xaf);        //display on
}


// Turns display off.
void displayOff(void)
{
  sendcommand(0xae);    //display off
}


// Clears the display by sendind 0 to all the screen map.
static void clear_display(void)
{
  unsigned char i,k;
  for(k=0;k<4;k++)  //4
  {
    setXY(0,k);    
    {
      for(i=0;i<128;i++)     //was 128
      {
        sendChar(0);         //clear all COL
        //delay(10);
      }
    }
  }
}
    

// Inits oled
static void init_OLED(void)
{
  
  sendcommand(0xae);//--turn off oled panel

  sendcommand(0x15);  //set column addresses
  sendcommand(0x00);  //start column  0
  sendcommand(0x7f);  //end column  127

  sendcommand(0x75);  //set row addresses
  sendcommand(0x00);  //start row  0
  sendcommand(0x7f);  //end row  127

  sendcommand(0x81);  //set contrast control
  sendcommand(0x80);  //50% (128/255)

  sendcommand(0xa0);   //remap configuration
  sendcommand(0x51);  //51 (To my understanding, this is orientation

  sendcommand(0xa1);  //start line
  sendcommand(0x00);

  sendcommand(0xa2);  //display offset
  sendcommand(0x10);

  sendcommand(0xa4);  //normal display
  //sendcommand(0xa5);  //all pixels on
  
  sendcommand(0xa8);  //set multiplex ratio
  sendcommand(0x7f);

  sendcommand(0xb1);  //set phase leghth
  sendcommand(0x51);

  sendcommand(0xb3);  //set dclk
  sendcommand(0x01);  //80Hz:0xc1 90Hz:0xe1  100Hz:0x00  110Hz:0x30 120Hz:0x50  130Hz:0x70   01

  sendcommand(0xab);  //Enable vReg
  sendcommand(0x01);  

  sendcommand(0xb6);  //set phase leghth
  sendcommand(0x01);

  sendcommand(0xbe); //Set vcomh voltage
  sendcommand(0x07);

  sendcommand(0xbc); //set pre-charge voltage
  sendcommand(0x08);

  sendcommand(0xd5); //second precharge period
  sendcommand(0x62);

  sendcommand(0xfd); //Unlock commands
  sendcommand(0x12);

  sendcommand(0xaf);
  
  clear_display();
  
}


Buleste

This is the font code

Code: [Select]
// Small 8x8 font
const unsigned char myFont[][8] PROGMEM = {
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00},
  {0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x00}, {0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x00}, {0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x00},
  {0x00, 0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x00}, {0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x08, 0x2A, 0x1C, 0x2A, 0x08, 0x00, 0x00}, {0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00},
  {0x00, 0xA0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, {0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, {0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00}, {0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00},
  {0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x00, 0x00}, {0x00, 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 0x00}, {0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x00},
  {0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00}, {0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 0x00}, {0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 0x00},
  {0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00}, {0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00}, {0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x00, 0xAC, 0x6C, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00}, {0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
  {0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00}, {0x00, 0x02, 0x01, 0x51, 0x09, 0x06, 0x00, 0x00}, {0x00, 0x32, 0x49, 0x79, 0x41, 0x3E, 0x00, 0x00},
  {0x00, 0x7E, 0x09, 0x09, 0x09, 0x7E, 0x00, 0x00}, {0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00}, {0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x00},
  {0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00}, {0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x00}, {0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x00},
  {0x00, 0x3E, 0x41, 0x41, 0x51, 0x72, 0x00, 0x00}, {0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00}, {0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x00}, {0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, {0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
  {0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, 0x00}, {0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x00}, {0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x00},
  {0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x00}, {0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x00}, {0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x00},
  {0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00}, {0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, 0x00}, {0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x00},
  {0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x00}, {0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x00}, {0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x00},
  {0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x00}, {0x00, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x00}, {0x00, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00}, {0x00, 0x41, 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00},
  {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00}, {0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, 0x00},
  {0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, 0x00, 0x00}, {0x00, 0x38, 0x44, 0x44, 0x28, 0x00, 0x00, 0x00}, {0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, 0x00, 0x00},
  {0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00}, {0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x00, 0x00}, {0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x00, 0x00},
  {0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00}, {0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x80, 0x84, 0x7D, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00}, {0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, 0x00, 0x00},
  {0x00, 0x7C, 0x08, 0x04, 0x7C, 0x00, 0x00, 0x00}, {0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00}, {0x00, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00},
  {0x00, 0x18, 0x24, 0x24, 0xFC, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7C, 0x08, 0x04, 0x00, 0x00, 0x00}, {0x00, 0x48, 0x54, 0x54, 0x24, 0x00, 0x00, 0x00},
  {0x00, 0x04, 0x7F, 0x44, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x3C, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00}, {0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x00},
  {0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x00}, {0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00}, {0x00, 0x1C, 0xA0, 0xA0, 0x7C, 0x00, 0x00, 0x00},
  {0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00}, {0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00},
  {0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00}, {0x00, 0x02, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00}
};

david_prentice

The SSD1327 is 128x128 with 16 shades of grey.

This means that you would need 128x128x4 bits of SRAM for a buffer.  i.e. 8kB of SRAM.

This is more SRAM than most Arduinos can afford to waste.

Yes,  you can ignore the grayscale and treat it as a monochrome display e.g. SSD1306 style.
Follow the Adafruit_SSD1306 style and you can use a 128x128x1 buffer i.e. 2kB

U8g2lib treats it as a monochrome display.  However U8g2lib has a sophisticated buffer scheme that can work with a "small" SRAM buffer.

Unfortunately the SSD1327 can only read its internal GRAM if you use the 8-bit parallel interface.
Neither SPI nor I2C interface permit GRAM read.

If you could read GRAM it is possible to draw bit-addressable graphics.  i.e. no need for any buffer at all.

The SSD1327 has internal GRAM memory organised as 128x128x4 bits
You can only address it as 64x128x8.   i.e. two pixels in one byte.

It seems crazy to me.   It would cost Solomon Systech nothing to provide individual pixel addressing.
No need to alter the interface hardware.   Just provide a 128 pixel wide X register.

Hey-ho.   It would be so nice if there already was such a secret register.

What target do you want to use?

David.

Buleste

I just want it as a simple monochrome display with 16 columns and maybe 4 rows.

It's mostly to be used for just displaying text with the odd special character if I can bring myself to designing them.

david_prentice

If you don't care about pixel-addressable graphics,  you just write the text without worrying about anything else.

I have an SSD1327 and it displays grayscale photos quite nicely.
It seems wasteful to just use mono on a grayscale display.

If you don't care,   you will find that a full colour ST7735 or ILI9163 will be much easier for displaying any text or graphics.

Much cheaper too.   And the TFT uses less current than the OLED when active.
If you can switch the TFT backlight on or off,   the TFT will give you better average current consumption.

David.

Buleste

Sadly they are both SPI and although I've got the option of a PCD8544 in the project I want to fit this library into, I2C is more reliable and uses less pins as I am using SPI already for SD card access.

At the moment using the 1306 on a Nano with my project I use up most of the Nanos memory

Sketch uses 28416 bytes (92%) of program storage space. Maximum is 30720 bytes.
Global variables use 1530 bytes (74%) of dynamic memory, leaving 518 bytes for local variables. Maximum is 2048 bytes.

david_prentice

I give up.   You started this topic.   The title says I2C.

If you replace the Nano  bootloader you would have more Flash.

Quite honestly,  U8g2lib only uses minimal  memory.   Choose your fonts carefullly.

David.

Buleste

I give up.   You started this topic.   The title says I2C.
And the two screens you suggested, ST7735 or ILI9163, are SPI.

Quote
If you replace the Nano  bootloader you would have more Flash.

Quite honestly,  U8g2lib only uses minimal  memory.   Choose your fonts carefullly.

David.
Even if I replaced the bootloader U8g2lib uses too much memory even with the smallest of fonts which is why I'm trying to write a small SSD1327 similar to the SSD1306 library.

david_prentice

#9
May 26, 2019, 10:07 pm Last Edit: May 26, 2019, 10:10 pm by david_prentice
Yes,  ST7735 etc are SPI.   It can share the hardware SPI bus with other devices.   But you still need a separate DC and CS pin.   (I prefer RESET to be controllable too)

Which U8g2lib fonts are you using?

What do you actually print?

Number fonts are very small
UPPERCASE fonts are fairly small
Regular 95 char ascii is same as as any other ascii font

Yes,  Extended and Unicode fonts can be enormous.

David.

Buleste

Again. u8g2 is too big for what I'm trying to do and what I'm trying to fit it into. Even with the smallest fonts.

It has to be a very small library to fit into a large over all project.

All I'm printing on screen is filenames and "playing", "stopped" etc and other messages but I want a nice clear large display and be able to fit all the programming into a Nano.

The SSD1327 1.5" is an ideal size and is I2C which is preferable as having two SPI devices connected has caused issues.

bitbank

#11
May 28, 2019, 11:12 am Last Edit: May 28, 2019, 11:14 pm by bitbank
Are there any small libraries for this screen other than the u8g2 libraries?

Preferably as small as possible.
I just ordered one from China last week. When it arrives, I'll create a compact library for drawing text and graphics. I just updated my SSD1306 library to fit better on AVR by shrinking the font data to 1344 bytes (3 sizes - 6x8, 8x8, 16x16) and the code is just a little bigger than that. I can see doing something similar with the SSD1327 and allowing you to specify the foreground and background text "color" as well as drawing pixels/lines as if the display is 64x128. I will drive it from the ATtiny85 as well to show off it's compactness :)
Library? We don't need no stinkin' library...we write our own

Buleste

I just ordered one from China last week. When it arrives, I'll create a compact library for drawing text and graphics. I just updated my SSD1306 library to fit better on AVR by shrinking the font data to 1344 bytes (3 sizes - 6x8, 8x8, 16x16) and the code is just a little bigger than that. I can see doing something similar with the SSD1327 and allowing you to specify the foreground and background text "color" as well as drawing pixels/lines as if the display is 64x128. I will drive it from the ATtiny85 as well to show off it's compactness :)

That sounds great. I'll have to have a look at your libraries.

olikraus

Quote
It has to be a very small library to fit into a large over all project.
Did you test the U8x8 interface, which comes with u8g2?
It should require much lesser RAM and FlashROM

Oliver

Buleste

Did you test the U8x8 interface, which comes with u8g2?
It should require much lesser RAM and FlashROM

Oliver
Doesn't have I2C support for the 128x128

Code: [Select]
//U8X8_SSD1327_SEEED_96X96_SW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // Seeedstudio Grove OLED 96x96
//U8X8_SSD1327_SEEED_96X96_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE); // Seeedstudio Grove OLED 96x96
//U8X8_SSD1327_EA_W128128_4W_SW_SPI u8x8(/* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8X8_SSD1327_EA_W128128_4W_HW_SPI u8x8(/* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8X8_SSD1327_MIDAS_128X128_4W_SW_SPI u8x8(/* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8X8_SSD1327_MIDAS_128X128_4W_HW_SPI u8x8(/* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

Go Up