probonopd
6/21/2015 - 9:42 PM

Drive 0.96" IIC I2C 128x64 OLED LCD Display Module M45 (has SSD1306 driver IC) connected to ESP-01 module (0=SDA, 2=SCL) http://www.ebay.de/

Drive 0.96" IIC I2C 128x64 OLED LCD Display Module M45 (has SSD1306 driver IC) connected to ESP-01 module (0=SDA, 2=SCL) http://www.ebay.de/itm/White-0-96-IIC-I2C-128X64-OLED-LCD-Display-Module-Arduino-STM32-AVR-51-M45-/291216700457

// ESP_i2c_OLED.ino
// Drive 0.96" IIC I2C 128x64 OLED LCD Display Module M45 (has SSD1306 driver IC)
// connected to ESP-01 module (0=SDA, 2=SCL)
// http://www.ebay.de/itm/White-0-96-IIC-I2C-128X64-OLED-LCD-Display-Module-Arduino-STM32-AVR-51-M45-/291216700457
// USD 3,80 shipped as of June 2015
// Based on mike-rankin/ESP_LUA_Loader
// TODO: Make a simple library out of it?

#include <Wire.h>

#define OLED_address  0x3c  // OLED I2C bus address

void setup()
{
#ifdef ARDUINO_ESP8266_ESP01
  Wire.pins(0, 2); // ESP-01 has only two I/O pins, 0=SDA, 2=SCL
#endif
  Wire.begin(); // Initialize I2C
  init_OLED(); // Initialize OLED Display
  reset_display();
}

// Small 8x8 font
unsigned char myFont[][8] = {
  {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}
};

void loop()
{
  sendStrXY("Hello!", 0, 0);
  sendStrXY("Arduino code", 1, 0);
  sendStrXY("running here", 2, 0);
  sendStrXY("with OLED on", 3, 0);
  sendStrXY("ESP8266", 4, 0);
  delay(4000);
  reset_display();
}

// Resets display depending on the actual mode.
static void reset_display(void)
{
  //sendcommand(0xae);		//display off
  unsigned char i, k;
  for (k = 0; k < 8; k++) //8
  {
    setXY(k, 0);
    {
      for (i = 0; i < 128; i++) SendChar(0);
    }
  }
  //sendcommand(0xaf);        //display on
}

// Actually this sends a byte, not a char to draw in the display
static void SendChar(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) in coordinates X Y, being multiples of 8.
// This means we have 16 COLS (0-15) and 8 ROWS (0-7).
static void sendCharXY(unsigned char data, int X, int Y)
{
  setXY(X, Y);
  Wire.beginTransmission(OLED_address); // begin transmitting
  Wire.write(0x40); // data mode
  for (int i = 0; i < 8; i++) //8
    Wire.write(pgm_read_byte(myFont[data - 0x20] + i));
  Wire.endTransmission();    // stop transmitting
}

// 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
}

// Set the cursor position in a 16 COL * 8 ROW map.
static void setXY(unsigned char row, unsigned char col)
{
  sendcommand(0xb0 + row);              //set page address
  sendcommand(0x00 + (8 * col & 0x0f)); //set low col address  //8
  sendcommand(0x10 + ((8 * col >> 4) & 0x0f)); //set high col address  //8

}

// 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++)
    {
      SendChar(pgm_read_byte(myFont[*string - 0x20] + i));
    }
    *string++;
  }
}

// Inits oled
static void init_OLED(void)
{
  sendcommand(0xae); // display off
  sendcommand(0xAE); // DISPLAYOFF
  sendcommand(0xD5); // SETDISPLAYCLOCKDIV
  sendcommand(0x80); // the suggested ratio 0x80
  sendcommand(0xA8); // SSD1306_SETMULTIPLEX
  sendcommand(0x2F); // --1/48 duty    //NEW!!!
  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(0xC8); // COMSCANDEC  Rotate screen 180 Deg
  sendcommand(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
  sendcommand(0x2e); // stop scroll
  sendcommand(0x20); // Set Memory Addressing Mode
  sendcommand(0x00); // Set Memory Addressing Mode ab Horizontal addressing mode
  setXY(0, 0);
  sendcommand(0xaf); // display on
}