Working code for ssd1306 display

Go To Last Post
34 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does someone has a working code for ssd1306 128x64 display. I need to run it on atmega328p with i2c on atmel.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

google is your friend:  https://github.com/adafruit/Adaf...

 

Jim

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nico444 wrote:
on atmel

You mean Atmel Studio ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes on Atmel Studio 7. I know that library but I can't make it work. This is why I need an example code

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please define "doesn't work"!

 

What hardware are you using?

 

What test capability do you have? Do you have live debug? Do you have (or have access to) a logic analyzer or an oscilloscope?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nico444 wrote:
I know that library but I can't make it work. This is why I need an example code

Most Arduino code is C++, so in AS7 start by creating a C++ project, C is a subset of C++, so it will still take C code as well.

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I recently wrote some code for an  SSD1306 128x64 I2C display for an ATmega328p.   The Adafruit library for SSD1306 reserves 1,000+ bytes of SRAM for a bitmap that gets entirely written to the SSD whenever the display is changed.  My code doesn't use this screen display buffer but does use the TWI AVR peripheral to update the SSD display.

 

I will attach it to my next message.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is the code for making an I2C-based SSD1306 OLED display work with the ATmega328P.
Start by adding all these define statements to your base code.  These give names to various
registers of the SSD:
// cut-and-paste the text below into your program.
 

#define SSD1306_CHAR_SIZE        6
#define SSD1306_OLED_SLA7              0x3C     //  SSD1306 controller,  I2C slave address
#define SSD1306_LASTLINE                0x07
#define SSD1306_COMMAND                 0x00
#define SSD1306_DATA                    0xC0
#define SSD1306_DATA_CONTINUE           0x40
#define SSD1306_SET_CONTRAST_CONTROL    0x81
#define SSD1306_DISPLAY_ALL_ON_RESUME   0xA4
#define SSD1306_DISPLAY_ALL_ON          0xA5
#define SSD1306_NORMAL_DISPLAY          0xA6
#define SSD1306_INVERT_DISPLAY          0xA7
#define SSD1306_DISPLAY_OFF             0xAE
#define SSD1306_DISPLAY_ON              0xAF
#define SSD1306_NOP                     0xE3
#define SSD1306_HORIZONTAL_SCROLL_RIGHT 0x26
#define SSD1306_HORIZONTAL_SCROLL_LEFT  0x27
#define SSD1306_SCROLL_VERT_AND_RIGHT   0x29
#define SSD1306_SCROLL_VERT_AND_LEFT    0x2A
#define SSD1306_DEACTIVATE_SCROLL       0x2E
#define SSD1306_ACTIVATE_SCROLL         0x2F
#define SSD1306_SET_VERT_SCROLL_AREA    0xA3
#define SSD1306_SET_LOWER_COLUMN        0x00
#define SSD1306_SET_HIGHER_COLUMN       0x10
#define SSD1306_MEMORY_ADDR_MODE        0x20
#define SSD1306_SET_COLUMN_ADDR         0x21
#define SSD1306_SET_PAGE_ADDR           0x22
#define SSD1306_SET_START_LINE          0x40
#define SSD1306_SET_SEGMENT_REMAP       0xA0
#define SSD1306_SET_MULTIPLEX_RATIO     0xA8
#define SSD1306_COM_SCAN_DIR_INC        0xC0
#define SSD1306_COM_SCAN_DIR_DEC        0xC8
#define SSD1306_SET_DISPLAY_OFFSET      0xD3
#define SSD1306_SET_COM_PINS            0xDA
#define SSD1306_CHARGE_PUMP             0x8D
#define SSD1306_SET_CLOCK_DIV_RATIO     0xD5
#define SSD1306_SET_PRECHARGE_PERIOD    0xD9
#define SSD1306_SET_VCOM_DESELECT       0xDB
/*##############################################################*/

//  global variables that need to be unchanged between each call to OLED_SetCursor() and OLED_DisplayChar().
uint8_t         OLEDlineNumber = 0, OLEDcursorPos = 0;

// Next comes two font tables that go into 1K of flash. The first table is for 7x5 chars and
//  it is the same table found in most libraries of graphics-based display controllers.
//   After the 7x5 table is a second table for making big digit
//  chars that are three rows high.  {0..9, plus colon : and space chars)
//  Least-sig-bit on upper top side of char column.  Bytes go left to right.
 // Vertical pixel alignment: 475 bytes in flash.
const uint8_t FontTable[][FONT_SIZE] PROGMEM = {
        0x00, 0x00, 0x00, 0x00, 0x00,   // space 00   20 hexASCII
        0x00, 0x00, 0x2f, 0x00, 0x00,   // !     01   21
        0x00, 0x07, 0x00, 0x07, 0x00,   // "     02   22
        0x14, 0x7f, 0x14, 0x7f, 0x14,   // #     03   23
        0x24, 0x2a, 0x7f, 0x2a, 0x12,   // $     04   24
        0x23, 0x13, 0x08, 0x64, 0x62,   // %     05   25
        0x36, 0x49, 0x55, 0x22, 0x50,   // &     06   26
        0x00, 0x05, 0x03, 0x00, 0x00,   // '     07   27
        0x00, 0x1c, 0x22, 0x41, 0x00,   // (     08   28
        0x00, 0x41, 0x22, 0x1c, 0x00,   // )     09   29
        0x14, 0x08, 0x3E, 0x08, 0x14,   // *     10   2a
        0x08, 0x08, 0x3E, 0x08, 0x08,   // +     11   2b
        0x00, 0x00, 0xA0, 0x60, 0x00,   // ,     12   2c
        0x08, 0x08, 0x08, 0x08, 0x08,   // -     13   2d
        0x00, 0x60, 0x60, 0x00, 0x00,   // .     14   2e
        0x20, 0x10, 0x08, 0x04, 0x02,   // /     15   2f
        0x3E, 0x51, 0x49, 0x45, 0x3E,   // 0     16   30
        0x00, 0x42, 0x7F, 0x40, 0x00,   // 1     17   31
        0x42, 0x61, 0x51, 0x49, 0x46,   // 2     18   32
        0x21, 0x41, 0x45, 0x4B, 0x31,   // 3     19   33
        0x18, 0x14, 0x12, 0x7F, 0x10,   // 4     20   34
        0x27, 0x45, 0x45, 0x45, 0x39,   // 5     21   35
        0x3C, 0x4A, 0x49, 0x49, 0x30,   // 6     22   36
        0x01, 0x71, 0x09, 0x05, 0x03,   // 7     23   37
        0x36, 0x49, 0x49, 0x49, 0x36,   // 8     24   38
        0x06, 0x49, 0x49, 0x29, 0x1E,   // 9     25   39
        0x00, 0x36, 0x36, 0x00, 0x00,   // :     26   3a
        0x00, 0x56, 0x36, 0x00, 0x00,   // ;     27   3b
        0x08, 0x14, 0x22, 0x41, 0x00,   // <     28   3c
        0x14, 0x14, 0x14, 0x14, 0x14,   // =     29   3d
        0x00, 0x41, 0x22, 0x14, 0x08,   // >     30   3e
        0x02, 0x01, 0x51, 0x09, 0x06,   // ?     31   3f
        0x32, 0x49, 0x59, 0x51, 0x3E,   // @     32   40
        0x7C, 0x12, 0x11, 0x12, 0x7C,   // A     33   41
        0x7F, 0x49, 0x49, 0x49, 0x36,   // B     34   42
        0x3E, 0x41, 0x41, 0x41, 0x22,   // C     35   43
        0x7F, 0x41, 0x41, 0x22, 0x1C,   // D     36   44
        0x7F, 0x49, 0x49, 0x49, 0x41,   // E     37   45
        0x7F, 0x09, 0x09, 0x09, 0x01,   // F     38   46
        0x3E, 0x41, 0x49, 0x49, 0x7A,   // G     39   47
        0x7F, 0x08, 0x08, 0x08, 0x7F,   // H     40   48
        0x00, 0x41, 0x7F, 0x41, 0x00,   // I     41   49
        0x20, 0x40, 0x41, 0x3F, 0x01,   // J     42   4a
        0x7F, 0x08, 0x14, 0x22, 0x41,   // K     43   4b
        0x7F, 0x40, 0x40, 0x40, 0x40,   // L     44   4c
        0x7F, 0x02, 0x0C, 0x02, 0x7F,   // M     45   4d
        0x7F, 0x04, 0x08, 0x10, 0x7F,   // N     46   4e
        0x3E, 0x41, 0x41, 0x41, 0x3E,   // O     47   4f
        0x7F, 0x09, 0x09, 0x09, 0x06,   // P     48   50
        0x3E, 0x41, 0x51, 0x21, 0x5E,   // Q     49   51
        0x7F, 0x09, 0x19, 0x29, 0x46,   // R     50   52
        0x46, 0x49, 0x49, 0x49, 0x31,   // S     51   53
        0x01, 0x01, 0x7F, 0x01, 0x01,   // T     52   54
        0x3F, 0x40, 0x40, 0x40, 0x3F,   // U     53   55
        0x1F, 0x20, 0x40, 0x20, 0x1F,   // V     54   56
        0x3F, 0x40, 0x38, 0x40, 0x3F,   // W     55   57
        0x63, 0x14, 0x08, 0x14, 0x63,   // X     56   58
        0x07, 0x08, 0x70, 0x08, 0x07,   // Y     57   59
        0x61, 0x51, 0x49, 0x45, 0x43,   // Z     58   5a
        0x00, 0x7F, 0x41, 0x41, 0x00,   // [     59   5b
        0x55, 0xAA, 0x55, 0xAA, 0x55,   //       60   5c Backslash (Checker pattern)
        0x00, 0x41, 0x41, 0x7F, 0x00,   // ]     61   5d
        0x04, 0x02, 0x01, 0x02, 0x04,   // ^     62   5e
        0x40, 0x40, 0x40, 0x40, 0x40,   // _     63   5f underscore
        0x00, 0x03, 0x05, 0x00, 0x00,   // `     64   60 apostrophe
        0x20, 0x54, 0x54, 0x54, 0x78,   // a     65   61
        0x7F, 0x48, 0x44, 0x44, 0x38,   // b     66   62
        0x38, 0x44, 0x44, 0x44, 0x20,   // c     67   63
        0x38, 0x44, 0x44, 0x48, 0x7F,   // d     68   64
        0x38, 0x54, 0x54, 0x54, 0x18,   // e     69   65
        0x08, 0x7E, 0x09, 0x01, 0x02,   // f     70   66
        0x18, 0xA4, 0xA4, 0xA4, 0x7C,   // g     71   67
        0x7F, 0x08, 0x04, 0x04, 0x78,   // h     72   68
        0x00, 0x44, 0x7D, 0x40, 0x00,   // i     73   69
        0x40, 0x80, 0x84, 0x7D, 0x00,   // j     74   6a
        0x7F, 0x10, 0x28, 0x44, 0x00,   // k     75   6b
        0x00, 0x41, 0x7F, 0x40, 0x00,   // l     76   6c
        0x7C, 0x04, 0x18, 0x04, 0x78,   // m     77   6d
        0x7C, 0x08, 0x04, 0x04, 0x78,   // n     78   6e
        0x38, 0x44, 0x44, 0x44, 0x38,   // o     79   6f
        0xFC, 0x24, 0x24, 0x24, 0x18,   // p     80   70
        0x18, 0x24, 0x24, 0x18, 0xFC,   // q     81   71
        0x7C, 0x08, 0x04, 0x04, 0x08,   // r     82   72
        0x48, 0x54, 0x54, 0x54, 0x20,   // s     83   73
        0x04, 0x3F, 0x44, 0x40, 0x20,   // t     84   74
        0x3C, 0x40, 0x40, 0x20, 0x7C,   // u     85   75
        0x1C, 0x20, 0x40, 0x20, 0x1C,   // v     86   76
        0x3C, 0x40, 0x30, 0x40, 0x3C,   // w     87   77
        0x44, 0x28, 0x10, 0x28, 0x44,   // x     88   78
        0x1C, 0xA0, 0xA0, 0xA0, 0x7C,   // y     89   79
        0x44, 0x64, 0x54, 0x4C, 0x44,   // z     90   7a
        0x00, 0x10, 0x7C, 0x82, 0x00,   // {     91   7b
        0x00, 0x00, 0xFF, 0x00, 0x00,   // |     92   7c
        0x00, 0x82, 0x7C, 0x10, 0x00,   // }     93   7d
        0x00, 0x06, 0x09, 0x09, 0x06};  // ~     94   7e

const uint8_t BigDigitFont[][36] PROGMEM = { // each SSD1306 data byte is 8 vertical pixels.
// 12 columns * 3 rows = 36 bytes per digit [ * 12 digit characters__432 bytes total ]
//         0    1    2    3    4    5    6    7    8    9   10   11
    0xfc,0xfe,0xfe,0x0f,0x07,0x07,0x07,0x07,0xcf,0xfe,0xfc,0xf8,  // character '0'
    0xff,0xff,0xff,0xf0,0x78,0x3c,0x1e,0x0f,0x07,0xff,0xff,0xff,  //
    0x3f,0x7f,0x7f,0xf8,0xf0,0xf0,0xf0,0xf0,0xf8,0x7f,0x7f,0x1f,  //

    0x00,0x00,0x40,0x60,0x70,0x78,0xfc,0xfe,0xff,0xff,0x00,0x00,  // character '1'
    0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,  //
    0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,  //

    0x38,0x3c,0x3e,0x0f,0x07,0x07,0x07,0x0f,0x1f,0xff,0xfe,0xfc,  // character '2'
    0xc0,0xe0,0xe0,0xf0,0x78,0x78,0x3c,0x1e,0x0f,0x0f,0x07,0x03,  //
    0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,  //

    0x38,0x3c,0x1e,0x0f,0x0f,0x0f,0x0f,0x0f,0x1e,0xfc,0xf8,0xf0,  // character '3'
    0x00,0x00,0x00,0x1e,0x1e,0x1e,0x1e,0x3e,0xff,0xff,0xe7,0x80,  //
    0x78,0xf8,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf8,0xff,0x7f,0x1f,  //

    0x00,0x00,0x00,0x00,0x00,0xc0,0xf0,0xf8,0x7e,0xff,0xff,0xff,  // character '4'
    0xe0,0xf0,0xf8,0xbe,0x9f,0x8f,0x83,0x81,0x80,0xff,0xff,0xff,  //
    0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0xff,  //

    0xff,0xff,0xff,0x87,0x87,0x87,0x87,0x87,0x87,0x07,0x07,0x07,  // character '5'
    0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x07,0xff,0xff,0xfc,  //
    0x3c,0x7c,0x78,0xf0,0xf0,0xf0,0xf0,0xf0,0x78,0x7f,0x3f,0x1f,  //

    0xf8,0xfc,0xfe,0x0f,0x07,0x07,0x07,0x07,0x07,0x0f,0x1e,0x1c,  // character '6'
    0xff,0xff,0xff,0x1e,0x0e,0x0e,0x0e,0x0e,0x1e,0xfe,0xfc,0xf8,  //
    0x3f,0x7f,0x7f,0xf0,0xe0,0xe0,0xe0,0xe0,0xf8,0x7f,0x3f,0x1f,  //

    0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0xff,0xff,0xff,0xff,  // character '7'
    0x00,0x00,0x00,0x00,0x80,0xe0,0xf8,0xfe,0x7f,0x1f,0x0f,0x03,  //
    0x00,0xc0,0xf0,0xfe,0xff,0x1f,0x07,0x01,0x00,0x00,0x00,0x00,  //

    0xf8,0xfe,0xff,0x07,0x07,0x07,0x07,0x07,0x8f,0xff,0xfe,0x78,  // character '8'
    0xe0,0xff,0xff,0x1f,0x0e,0x0e,0x0e,0x1f,0x3f,0xff,0xf9,0xe0,  //
    0x1f,0x7f,0x7f,0xf0,0xe0,0xe0,0xe0,0xf0,0x78,0x7f,0x3f,0x1f,  //

    0xfc,0xfe,0xff,0x0f,0x07,0x07,0x07,0x07,0x0f,0xff,0xfc,0xf8,  // character '9'
    0x1f,0x3f,0x3f,0x7c,0x78,0x78,0x78,0x78,0x3c,0xff,0xff,0xff,  //
    0x00,0x70,0xf0,0xf0,0xf0,0xf0,0x70,0x78,0x7c,0x3f,0x3f,0x0f,  //

    0x00,0x00,0x00,0x60,0xf0,0xf8,0xf8,0xf0,0x60,0x00,0x00,0x00,  // character ':'
    0x00,0x00,0x00,0x00,0x80,0xc1,0xc1,0x80,0x00,0x00,0x00,0x00,  //
    0x00,0x00,0x00,0x03,0x07,0x0f,0x0f,0x07,0x03,0x00,0x00,0x00,  //

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // character ' '
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  //
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

//  here are the functions for using the SSD1306, followed by documentation.

//~~~~~~~~~~~~~~~~~~~~~~~LOW-level OLED_I2C  @ 180 lines of code ~~~~
void i2c_initialise()  {   //  should called at the beginning of main() {Arduino:  by setup() when not using Wire.h}
        TWBR = 12;         //  400KHz   use 0x62 = @80KHz
        TWSR = 0x01;
        TWCR = (1<<TWEN);
}//~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~
void OLED_sendCommand(uint8_t myCmd)   {
        TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); // send START
        while(!(TWCR & (1 << TWINT)));  // delay until TWINT set
        TWDR = OLED_SLA7 << 1;   // send SLA    8-bit SLAw = 0x78
        TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

        TWDR = SSD1306_COMMAND; // send D/C_sentinel byte for command:0x00
        TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

        TWDR = myCmd;   // I2C write, wait until completed
        TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

        TWCR = ( (1<<TWINT)|(1<<TWEN)|(1<<TWSTO) ); // I2C STOP
}//~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~
void OLED_clear() {
        OLED_sendCommand(SSD1306_SET_COLUMN_ADDR);   // opcode:0x21
        OLED_sendCommand(0);     // start at left edge of screen
        OLED_sendCommand(127);   // end at right edge of screen

        OLED_sendCommand(SSD1306_SET_PAGE_ADDR);     // opcode:0x22
        OLED_sendCommand(0);     // start at the top row
        OLED_sendCommand(7);     // end at the bottom row

        TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); // send START
        while(!(TWCR & (1 << TWINT)));  // delay until TWINT set
        TWDR = OLED_SLA7 << 1;   // send SLA  8-bit SLAw = 0x78
        TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

        TWDR = SSD1306_DATA_CONTINUE;   // send D/C sentinal byte 0x40
        TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

        // TWI NOT using Wire.h   128 bytes (8 bits vertical) per row * 8 char rows = 1024
        // Send 64 TWI messages { START:SLAw:0x40:16 bytes of 0x00:STOP }  1024 data bytes total
        for (uint16_t scrClearIndex=0; scrClearIndex<1024; scrClearIndex++) {  // (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8)
            TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); // send START
            while(!(TWCR & (1 << TWINT)));  // delay until TWINT set
            TWDR = OLED_SLA7 << 1;   // 8-bit SLAw = 0x78
            TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay

            TWDR = 0x40;  // send D/C_sentinal byte for data stream
            TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

            for (uint8_t x=0; x<16; x++) {
                TWDR = 0x00;  // all eight pixels in the column are off.
                TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));
                scrClearIndex++;  // 16 bytes per I2C transmission__64 transmissions per screen
            }
            scrClearIndex--;
            TWCR = ( (1<<TWINT)|(1<<TWEN)|(1<<TWSTO) ); // I2C STOP
        }
}//~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~
void OLED_Init(void) {  // cmd: send START, 8bitSLA, D/C sentinal=0x00, command_value, STOP
        OLED_sendCommand(SSD1306_DISPLAY_OFF);          //   0xAE
        OLED_sendCommand(SSD1306_SET_CLOCK_DIV_RATIO);  //   0xD5
        OLED_sendCommand(0x80);                         //   0x80
        OLED_sendCommand(SSD1306_SET_MULTIPLEX_RATIO);  //   0xA8
        OLED_sendCommand(0x3F);                         //   0x3F
        OLED_sendCommand(SSD1306_SET_DISPLAY_OFFSET);   //   0xD3
        OLED_sendCommand(0x0);                          //   0x00
        OLED_sendCommand(SSD1306_SET_START_LINE | 0x00); //   0x40
        OLED_sendCommand(SSD1306_CHARGE_PUMP);          //   0x8D
        OLED_sendCommand(0x14);                         //   0x14
        OLED_sendCommand(SSD1306_MEMORY_ADDR_MODE);     //   0x20
        OLED_sendCommand(0x00);                         //   0x00
        OLED_sendCommand(SSD1306_SET_SEGMENT_REMAP | 0x01);// 0xA1
        OLED_sendCommand(SSD1306_COM_SCAN_DIR_DEC);     //   0xC8
        OLED_sendCommand(SSD1306_SET_COM_PINS);         //   0xDA
        OLED_sendCommand(0x12);                         //   0x12
        OLED_sendCommand(SSD1306_SET_CONTRAST_CONTROL); //   0x81
        OLED_sendCommand(0xCF);                         //   0xCF
        OLED_sendCommand(SSD1306_SET_PRECHARGE_PERIOD); //   0xD9
        OLED_sendCommand(0xF1);                         //   0xF1
        OLED_sendCommand(SSD1306_SET_VCOM_DESELECT);    //   0xDB
        OLED_sendCommand(0x40);                         //   0x40
        OLED_sendCommand(SSD1306_DISPLAY_ALL_ON_RESUME);//   0xA4
        OLED_sendCommand(SSD1306_NORMAL_DISPLAY);       //   0xA6
        OLED_sendCommand(SSD1306_DISPLAY_ON);           //   0xAF
        OLED_clear();
}//~~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~
void OLED_SetCursor(uint8_t myLineNumber,uint8_t myColumnPosition) {
        if( (myLineNumber <= SSD1306_LASTLINE) && (myColumnPosition <= 127) ) {
            OLEDlineNumber = myLineNumber;     // global var: current line number
            OLEDcursorPos =  myColumnPosition; // global var: current cursor position

            OLED_sendCommand(SSD1306_SET_COLUMN_ADDR);
            OLED_sendCommand(myColumnPosition);
            OLED_sendCommand(127);

            OLED_sendCommand(SSD1306_SET_PAGE_ADDR);
            OLED_sendCommand(myLineNumber);
            OLED_sendCommand(7);

            TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); // send START
            while(!(TWCR & (1 << TWINT)));  // delay until TWINT set
            TWDR = OLED_SLA7 << 1;   // 8-bit SLAw = 0x78  7-bitSLA=0x3C  SSD1306 controller
            TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));

            TWDR = SSD1306_DATA_CONTINUE;   // 0x40
            TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT)));  // TWINT?set delay
        }
}//~~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~
void OLED_GoToLine(uint8_t myLine) {
        if( myLine < 8) {
            OLEDlineNumber = myLine;
            OLED_SetCursor(OLEDlineNumber, 0);
        }
}//~~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~
void OLED_GoToNextLine() {      // Increment and roll-over the current line number.
        OLEDlineNumber++;       // global var for current line number
        OLEDlineNumber = OLEDlineNumber & 0x07; // roll-over back to top after 8 lines
        OLED_SetCursor(OLEDlineNumber, 0);
}//~~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~~~
void OLED_DisplayChar(uint8_t myDisplayChar) {
        uint8_t charColumnBitMap, charBitMapIndex = 0;

        if(((OLEDcursorPos + FONT_SIZE) >= 128) || (myDisplayChar=='\n')) { // font size=5
//      If the line has no more room for complete chars OR NewLine command,
//      then move the cursor to next line
            OLED_GoToNextLine();
        }
        if(myDisplayChar != '\n') {
            myDisplayChar = myDisplayChar - 0x20; // As the lookup table starts from Space(0x20)
            while(1) {
               charColumnBitMap = pgm_read_byte(&FontTable[myDisplayChar][charBitMapIndex]);
               TWDR = charColumnBitMap;
               TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay
               OLEDcursorPos++;
               charBitMapIndex++;
               if( charBitMapIndex == FONT_SIZE) {   // Exit the loop after sending five bytes
                  TWDR = 0x00;  // last column of char is one column of space between chars.
                  TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay
                  OLEDcursorPos++;
                  break;
               }    }    }
}//~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~~~
void OLED_DisplayString(uint8_t *ptr) {
        while(*ptr) OLED_DisplayChar(*ptr++);
}//~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~~

void displayBigDigit(uint8_t myDigit, uint8_t myDigitRow, uint8_t myDigitColumn) {
        uint8_t charColumnBitMap, columnIndex = 0, rowIndex = 0, fullDigitIndex=0;
        
        if ( (myDigitRow <= 5) && (myDigitColumn <= 116) ) { // full digit gets displayed
            if (myDigit >= 0 && myDigit <= 9 ) {
              for (rowIndex=0; rowIndex<3; rowIndex++) {
                 OLED_SetCursor(myDigitRow + rowIndex, myDigitColumn);
                 for (columnIndex = 0; columnIndex < 12; columnIndex++) {
                    charColumnBitMap = pgm_read_byte(&BigDigitFont[myDigit][fullDigitIndex]);
                    TWDR = charColumnBitMap;
                    TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay
                    fullDigitIndex++;
                 }
              }
            }
            
            if (myDigit == 10 ) {
               for (rowIndex=0; rowIndex<3; rowIndex++) {
                  OLED_SetCursor(myDigitRow + rowIndex, myDigitColumn);
                  for (columnIndex = 0; columnIndex < 12; columnIndex++) {
                      charColumnBitMap = pgm_read_byte(&BigDigitFont[10][fullDigitIndex]);
                      TWDR = charColumnBitMap;
                      TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay
                      fullDigitIndex++;
                  }
               }
            }    // myDigit 10
              
            if (myDigit == 11 ) {
               for (rowIndex=0; rowIndex<3; rowIndex++) {
                  OLED_SetCursor(myDigitRow + rowIndex, myDigitColumn);
                  for (columnIndex = 0; columnIndex < 12; columnIndex++) {
                      charColumnBitMap = pgm_read_byte(&BigDigitFont[11][fullDigitIndex]);
                      TWDR = charColumnBitMap;
                      TWCR = ((1<<TWINT)|(1<<TWEN)); while(!(TWCR & (1<<TWINT))); // TX?done delay
                      fullDigitIndex++;
                  }
               }
            }   // myDigit 11
        }   // myDigitRow  5..116
}/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */


/* OLED display techniques:  numbers; flash strings, bitmaps;
-----------
Numbers:  Values that change and need to be updated:
-----------
            uint8_t myBuffer[22];

            OLED_SetCursor(0, 11 * CHAR_SIZE); //=6   top line 0, mid-screen char (0-20)
            itoa(integer_Variable_Name, myBuffer, 10);   // use dtostrf() for floats
            OLED_DisplayString(myBuffer);
-----------
Individual Characters
-----------OLED_DisplayChar(uint8_t myDisplayChar);

-----------
SRAM strings
-----------OLED_DisplayString(uint8_t *ptr);
 
Constant Number values in program memory:
----------- uint16_t workFMfreq, myFMpresetFreq;
            float displayFMfrequency ;
            byte highFMreg3, lowFMreg3, myBuffer[8];

            OLED_SetCursor(7, 16 * CHAR_SIZE); //=6   bottom line 7, right screen char (0-20)
            myFMpresetFreq = pgm_read_word(&FMstationPreset[currentFMstationIndex]);
            displayFMfrequency  =  (float) myFMpresetFreq / 100;
            dtostrf(displayFMfrequency,4,1,myBuffer); // 4 chars, 1 digit after dec point
            OLED_DisplayString(myBuffer); // dtostrf(value,strSize,decPtCnt,buffer);
-----------
Flash strings:  constant strings that are stored in program memory:
-----------
const char String00[] PROGMEM = "KFBW";   //  FM _The Buzz
const char String01[] PROGMEM = "KLTH";   //  The Eagle
const char String02[] PROGMEM = "KXRY";   //  progressive independent
const char String03[] PROGMEM = "KXJM";   //  Jam'n 1075
const char * const  StringArray[ 4 ] PROGMEM = {String00, String01, String02, String03};

            uint8_t myBuffer[22], *myPtrToFlashString;

            OLED_SetCursor(2,0 * SSD1306_CHAR_SIZE);  // = 6    starting row:char column pixel
            myPtrToFlashString = (char *) pgm_read_word (& StringArray
); strcpy_P ((char *) myBuffer, myPtrToFlashString); OLED_DisplayString(myBuffer); ----------- BitMaps: used for real-time clock's hours:minutes display: //offset 0-11; row 0-5; BIGDIGITSPACING=15 ----------- displayBigDigit(digit_offset, 5, 1 * BIGDIGITSPACING); */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOW-level OLED_I2C ~~~~~~~~~~~~~~~~~~~~~~~~~

 

Last Edited: Thu. Jan 2, 2020 - 01:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It gives me several errors:

FONT_SIZE, OLED_SLA7, FontTable and BigDigitFont are undeclared. What do I have to define?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you define the first two the others will take care of them selves.

#define FONT_SIZE 475     //this value is in the comments above the font table

#define OLED_SLA7 0xnn  //where nn is 7 bit address of the OLED I2C address

 

Jim

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed, I see no definition for  FONT_SIZE.

 

Also no  OLED_SLA7 - but there is:

Simonetta wrote:

#define SSD1306_CHAR_SIZE        6
#define SSD1306_OLED_SLA7              0x3C     //  SSD1306 controller,  I2C slave address
#define SSD1306_LASTLINE                0x07

 

FontTable and BigDigitFont are  here:

Simonetta wrote:

const uint8_t FontTable[][FONT_SIZE] PROGMEM = {
        0x00, 0x00, 0x00, 0x00, 0x00,   // space 00   20 hexASCII
        :
        :
        0x00, 0x06, 0x09, 0x09, 0x06};  // ~     94   7e

const uint8_t BigDigitFont[][36] PROGMEM = { // each SSD1306 data byte is 8 vertical pixels.
// 12 columns * 3 rows = 36 bytes per digit [ * 12 digit characters__432 bytes total ]
//         0    1    2    3    4    5    6    7    8    9   10   11
    0xfc,0xfe,0xfe,0x0f,0x07,0x07,0x07,0x07,0xcf,0xfe,0xfc,0xf8,  // character '0'
    :
    :
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

 

So the FontTable definition is broken by lack of the FONT_SIZE definition;

 

the BigDigitFont definition is probably broken because the code before it (the FontTable) is broken.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry about missing these two.  FONT_SIZE  is 5.     OLED_SLA7  is 0x3C, the I2C slave address in 7-bits that gets shifted left one bit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are still the errors on the  

const uint8_t FontTable[][FONT_SIZE] PROGMEM = {

and

const uint8_t BigDigitFont[][36] PROGMEM = {

It says:        expected '=', ',', ';', 'asm' or '__attribute__' before 'PROGMEM' 

 

And FontTable and BigDigitFont still undeclared

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're going to have to show the complete code as you have it, and the complete error messages.

 

Use copy & paste.

 

It says:        expected '=', ',', ';', 'asm' or '__attribute__' before 'PROGMEM' 

Probably means there's something wrong before those lines.

 

See: https://www.avrfreaks.net/commen...

 

And FontTable and BigDigitFont still undeclared

Of course! Having got errors in those lines means that you do not have valid declarations of those things!

 

Again, fix the first-reported error first - and others will fall into place.

 

 

Are you building as 'C' or C++ ?

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note that PROGMEM requires   <avr/pgmspace.h>  - so have you #included that?

 

https://www.nongnu.org/avr-libc/user-manual/pgmspace.html

 

 

If you're building as 'C', see: https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 Note that PROGMEM requires   <avr/pgmspace.h>  - so have you #included that? 

That was the problem, now it works.

 

Now I can display strings and numbers but the characters are too small. How do I set a bigger size?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nico444 wrote:
the characters are too small. How do I set a bigger size?

You have two or more choices, scale the existing font i.e take the 5x7 and make  it say 10x14 by making each dot, two dots tall and wide, or...

create a new font (and table) for a larger size, similar to the big number table.

Dot matrix displays are a pain as you have to draw every dot, but that also means it is more flexible, you can create anything you want.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The program memory include file is not declared because this is a sample library to be cut-and-paste'd into an existing program when an OLED I2C screen is attached to a pre-existing circuit, and because I use the Arduino IDE, which appears to include the progmem.h file in the background (along with stdio.h , etc...) when the .ino file the sketch)  is compiled.

 

There are two kinds of graphic displays:  one has one bit per pixel and the other uses two bytes per pixel.  This OLED SSD1306 is one of the most common bit-per-pixel type, along with the Nokia 5110 graphics LCD controller.   The TFT (thin film transistor; "tiny flat television") displays that usually have a red PCB base define a color for each pixel with 5 bits for red: 6 bits for green, and 5 bits for blue making 65536 possible colors per pixel.  The 5-6-5 bits combine into two bytes.

 

Expanding characters from 7x5 to 14x10 or 21x15 is easy to do with the two-byte-pixel displays, but really hard with 8 pixels-per-byte displays like the SSD1306.  Do an internet and GitlLab search for older code that uses the Nokia 5110 display.  The display routines should be similar for use by this SSD1306 because they use the more-or-less same method for displaying pixels.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What if I use a font generator like this one?  http://oleddisplay.squix.ch/#/home  

 

If I can, how do I add the that code to the main code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Perhaps time to go back to the original library, and get that one working?

 

This suggests that it can do at least 2 sizes:

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It would be nice if I only knew how to do it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The "DEADBEEF" display chars are 14 pixels tall vertically and 10 pixels wide horizontally. The SSD writes 8 pixels vertically at a time to each of the 1024 internal screen-display memory locations.  One byte per column of 8 rows: bit 0 of the column is on the top of the column.  Each char uses 2 bytes for each of the 10 columns (14 pixels plus 2 pixels for vertical spacing between the chars).  For a full ASCII char set, you need 20 * 96 or 1920 bytes of flash memory for the font-data table.

 

Every font or bit-map generator that I've seen for the Nokia5110/SSD1306 is next-to-useless due lack of any or any meaningful documentation on the part of the people who either wrote or posted the code.  The application linked in the message above is no exception.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So what is the best way to increase the characters' size?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are using a mega328P i.e. the same chip used by Arduino Uno.
.
You can run Arduino code on your chip. Just select a board with the same F_CPU .
All the Arduino libraries support different fonts. Some even allow you to print in x1 x2 x3 sizes e.g. the photo in #21
.
Yes, you can write your own C library. But life is more reliable if you use proven code.
There is C code for GCC. Codevision comes with graphics libraries for SSD1306 and most other controllers.
You just need to run the GCC or CV examples. Read the documentation. Write your ownn app that calls the proven library functions.
.
It is the same as learning how to operate a TV or motor car e.g. turn the steering wheel in the correct direction.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Perhaps time to go back to the original library, and get that one working?

nico444 wrote:
It would be nice if I only knew how to do it.

 

By the same process that we've used to resolve the errors you had with Simonetta 's code:

  1. Read the error messages
  2. Fix what they tell you is wrong
  3. Address the first-reported error first.

 

That's the way that you go about any programming task - it is not specific to AVR, or to microcontrollers - or even to 'C'.

 

It does rather seem that you are "in over your head" here: getting a graphic display working is not a beginner project - you should probably take a few steps back, and build up some basic skills

 

As David says, it's the same as learning any new skill: you need to start with the basics, lay good foundations, and build up step-by-step - rather than leap into something over-ambitious.

 

See:  https://www.avrfreaks.net/comment/1138166#comment-1138166

 

And:  https://www.avrfreaks.net/comment/2079906#comment-2079906

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To make bigger characters you need to have a 'font table' for the big characters.  This is set of bit-maps for each char.  They are sorted in character order.  So if you know that each char is 20 bytes in size and that the char for capital A is at offset 65 and the font-table starts at char #32, then the bit-map data for capital A starts at offset 20*31 from the address of the table starting position in memory.   Then you need a software routine that puts this char's bit-map onto the SSD1306 graphics screen.  There is a different routine for each font-table.

   There are several downloadable programs that make font tables from the fonts used by the PC.  But they don't work for the SSD1306 because the 1306 has its font data in vertical order, and the other TFT displays have their font data in horizontal order.

  So to make your own big chars, you need to make your own font tables and display routines, or write a routine that takes the font tables generated by the TFT-oriented programs and converts them to SSD1306 format.  I made one table for the bigDigit routine in the code above.  But it took a lot of time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can't I simply add the code of the font generator (http://oleddisplay.squix.ch/#/home) in your code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The SQUIX site will generate three different font formats.

It makes no attempt to describe the formats.

 

Likewise Simonetta does not seem to describe his font format.

 

Seriously.   I would write Arduino code.   There are several Arduino SSD1306 libraries.    Most support Adafruit Free Font format.

Others support the other "mystery SQUIX" formats.

 

If you want to develop your own graphics code it is a complex project.   (But you can steal a lot of ideas from the existing libraries)

 

It is worth explaining your project.   It makes quite a difference to which SSD1306 library you might choose.

A text-only project requires no buffers.    A text + graphics project has to plot pixels carefully.    Commonly,  you write pixels to a buffer in SRAM.   Then redraw the display from the SRAM buffer in one go.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The BigDigits font characters are 24 pixels high (vertical) and 12 pixels wide.  To make a digit appear, set the cursor position of the SSD,  then get the first 12 bytes of the char from the font table.  Write these 12 bytes to the SSD.   This puts the top row of three rows (8 pixels stacked with the Least Sig pixel on top) on the display.  Move the cursor to the same starting column, but one entire row below.  Write the next 12 bytes from the font table.  This makes the middle row.  Finally reposition the cursor for a third time, again directly below the first and second row's starting column.  Write the final 12 bytes from the char table (36 bytes per digit: three rows of 12 bytes) to complete the big digit's display.

 

I tried Adafruit's SSD1306 library, but this library reserves 1024 bytes of SRAM to make a copy of the SSD's screen in SRAM.  Then after a single pixel is changed, the Adafruit display routine writes this entire 1024 byte buffer to the SSD1306.  Which works, but it wastes a lot of time, especially with 100KHz I2C.  It takes 90+ milliSeconds (10uS per bit == 90 uS (8 bits plus ACK) x 1024) to change one pixel.  Plus I needed the SRAM space for several other libraries to use.

 

This one-pixel-per-bit:8-stacked-bits-in-a-vertical-column per byte format is also used by the Nokia 5110 screen, which was very popular about ten years ago.  Any bit-map editor that was designed for Nokia 5110 use should make valid bit-map data for the SSD1306.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,  it would be expensive to write the whole screen for one pixel.

In practice you write the whole screen to the buffer before displaying it.   The Adafruit library updates the screen at 400kHz.

If you don't worry about graphics,  you can write text on 8-row boundaries without any buffer.

 

However,  if you have a graphics display,  you might just as well use attractive fonts and regular graphics.

U8g2lib will work with a small buffer.     It can use Latin, Greek, Arabic, Chinese, ... fonts

Adafruit_SSD1306 uses 1024 bytes for a 128x64 display.    It can use FreeFonts

 

Just be careful with your SRAM use on a mega328.   e.g. store fonts, tables, text messages in Flash

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pls can u upload the code or hex file i want to use bengali ,hindi ,english fonts

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

@pihu

 

STOP begging for code on both old(very old) and current threads!

 

Start a thread of your own telling us what you want to accomplish....other than annoy everyone.

 

JIm - Moderator

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In #9, Simonetta wrote:
Here is the code for making an I2C-based SSD1306 OLED display work with the ATmega328P

nico444 wrote:
It gives me several errors

 

More issues with that code discussed here:

 

https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...