Edit 09.12.2016: I added Arial_16x24.h and Arial_24x40 (really a 24x36, but I had to keep a multiple of 8), digits only, created with GLCD Font Creator (I had to edit the result slightly manually). See images below. So I can confirm that adding any further fonts created with GLCD Font Creator works (I run it on Linux in on BTW) and is only limited by how much fits into the µC (e.g. the font size 16x24 didn't fit with all its printable ASCII characters, but I really need the digits only).
Regarding this. I too couldn't find a lib that would support bigger than the default 5x8 font size and even compile ("including the Adafruit, U8g2, etc." indeed), needed I2C support aside.
Tried:
Compiling this, but even after commenting out the whole setup(), it says:
/home/user/energia-1.6.10E18/hardware/tools/msp430/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld: ssd1306_128x32_i2c.ino.elf section `.data' will not fit in region `ram'
/home/user/energia-1.6.10E18/hardware/tools/msp430/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld: region `ram' overflowed by 264 bytes
collect2: ld returned 1 exit status
exit status 1
Error compiling for board MSP-EXP430G2553LP.
Compiling the original Adafruit's libs 1+2, but even after commenting out the whole setup(), it still says again:
/home/user/energia-1.6.10E18/hardware/tools/msp430/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld: ssd1306_128x64_i2c__test2.ino.elf section `.data' will not fit in region `ram'
/home/user/energia-1.6.10E18/hardware/tools/msp430/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld: region `ram' overflowed by 764 bytes
collect2: ld returned 1 exit status
exit status 1
Error compiling for board MSP-EXP430G2553LP.
(BTW: It looks like the latest git grew from 264 to 764 bytes.)
If anyone could get those Adafruit libs to work, that would be nice for everyone.
Meanwhile I did my own lib where the most was already done by/credits go to: this and this.
SSD1306.h
#if defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
#include "Energia.h"
#else // error
#error Platform not supported
#endif
#ifndef SSD1306_h
#define SSD1306_h
#include "Terminal6.h"
#include "Terminal12.h"
#include "Arial_16x24.h"
#include "Arial_24x40.h"
class SSD1306 {
public:
SSD1306(uint8_t _BITn, uint8_t _BITn2);
void begin(uint8_t contrast, boolean inverse);
void printS();
void printE();
void text(String string, uint8_t font_size);
private:
void printC(const unsigned char* Array, unsigned int length);
void printD(const unsigned char Data);
uint8_t i, j; // used in: text()
void text__continue_cursor_to_end_of_row(String s, uint8_t font_size);
uint8_t width, rows;
uint16_t i2;
};
#endif
SSD1306.cpp
#include "SSD1306.h"
#if defined(__MSP430G2553__) // LaunchPad MSP430G2553 specific
SSD1306::SSD1306(uint8_t _BITn, //
uint8_t _BITn2 //
) {
// Configure OLED pins for I2C
P1SEL |= _BITn + _BITn2; // Assign I2C pins to USCI_B0
P1SEL2 |= _BITn + _BITn2; // Assign I2C pins to USCI_B0
}
#else
#error Platform not supported
#endif
void SSD1306::begin(uint8_t contrast, boolean inverse) {
const unsigned char Init[] = { // https://www.adafruit.com/datasheets/SSD1306.pdf
0xAE, // Display off
0x81, // Set Contrast Control for BANK0 (81h)
contrast, // This command sets the Contrast Setting of the display. The chip has 256 contrast steps from 00h to FFh. The
// segment output current increases as the contrast step value increases.
0x20, // Set Memory Adress Mode
0x00, // Horizontal Adressing Mode
0x21, // Set Column Adress
0x00, // Start Adress 0
0x7F, // End Adress 127
0x22, // Set Page Adress
0x00, // Start Adress 0
0x07, // End Adress 7
0x40, // Set start line adress 0
0xA1, // Set Segment Re-map (A0h/A1h) --set segment re-map 0 to 127
0xA8, // Set Multiplex Ratio (A8h) (1 to 64)
0x3F, // This command switches the default 63 multiplex mode to any multiplex ratio, ranging from 16 to 63.
// The output pads COM0~COM63 will be switched to the corresponding COM signal.
0xC8, // Set COM Output Scan Direction to normal mode
0xD3, // set display offset
0x00, // 0
0x8D, // Set Charge Pump Setting
0x14, // ON
0xDA, // Set COM Pins Hardware Configuration (DAh)
0x12, // alternative + disable remap
0xD5, // Set Display Clock Divide Ratio/ Oscillator Frequency (D5h)
0x80, // divide by 1 and medium freq
0xD9, // Set Pre-charge Period (D9h)
0x22, // medium (reset value)
0xDB, // Set Vcomh regulator output
0x20, // 0.77 x Vcc
(inverse==false?0xA6:0xA7), // Set Normal/Inverse Display (A6h/A7h)
0xA4, // Output follows RAM Content
0xAF // Display on
};
const unsigned char Mod[] = {0xA5};
printC(Init,31);
__delay_cycles(5000000);
printC(Mod,1);
}
void SSD1306::printC(const unsigned char* Array, unsigned int length){
UCB0CTL1 = UCSWRST;
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC; // I2C master mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 0x15; // < 400 kHz
UCB0I2CSA = 0x3C; // address
UCB0CTL1 &= ~UCSWRST;
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
while (!(IFG2 & UCB0TXIFG));
unsigned int c;
for(c = 0; c < length; c++){
UCB0TXBUF = 0x80;
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = Array[c];
while (!(IFG2 & UCB0TXIFG));
}
UCB0CTL1 |= UCTXSTP;
}
void SSD1306::printS(void){
UCB0CTL1 = UCSWRST;
UCB0CTL0 = UCMODE_3 + UCMST + UCSYNC; // I2C master mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 0x15; // < 400 kHz
UCB0I2CSA = 0x3C; // address
UCB0CTL1 &= ~UCSWRST;
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = 0x40;
}
void SSD1306::printD(const unsigned char Data){
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = Data;
}
void SSD1306::printE(void){
while (!(IFG2 & UCB0TXIFG));
UCB0CTL1 |= UCTR + UCTXSTP;
}
/*
* Usage: One call per row and the font size heights must be equal to 64.
* Example:
* myOLED.text("",2); // 3 rows -- 16x24 font size
* myOLED.text("----Hello World !----",0); // 1 row -- 5x 8 font size
* myOLED.text("",1); // 2 rows -- 11x16 font size
* myOLED.text("---------------------",0); // 1 row -- 5x 8 font size
* myOLED.text("",0); // 1 row -- 5x 8 font size
* //= 8 rows -- = 64 pixels
* s: The string you want to print.
* font_size: Choose a font size {0, 1, 2, 3}, one per row.
* 0 (5x8 pixels), 1 (11x16 pixels), 2 (16x24 pixels) or 3 (24x36 pixels).
*/
void SSD1306::text(String s, uint8_t font_size) {
if(s.length() > 0) {
if (font_size==0) {
if(s.length() < 22) {
for (j=0; j<s.length(); j++) {
for (i=0; i<5; i++)
printD(Terminal6x8[s.charAt(j)-' '][i]);
printD(0x00); // put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
} else
text("-ERROR:Exceeds row-",font_size);
} else if (font_size==1) {
if(s.length() < 11) {
// print first part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<11; i++)
printD(Terminal11x16[s.charAt(j)-' '][2*i]);
printD(0x00); // put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print second part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<11; i++)
printD(Terminal11x16[s.charAt(j)-' '][2*i+1]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
} else
text("-ERR:long-",font_size);
} else if(font_size == 2) {
if(s.length() < 8) {
// print first part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<16; i++)
printD(Arial16x24[s.charAt(j)-'0'][i*3]);
printD(0x00); // put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print second part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<16; i++)
printD(Arial16x24[s.charAt(j)-'0'][i*3+1]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print third part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<16; i++)
printD(Arial16x24[s.charAt(j)-'0'][i*3+2]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
} else
text("",font_size); // since this Arial font size only has numbers included, so instead of displaying an error-text, we display nothing
} else if(font_size == 3) {
if(s.length() < 6) {
// print first part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<24; i++)
printD(Arial24x40[s.charAt(j)-'0'][i*5]);
printD(0x00); // put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print second part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<24; i++)
printD(Arial24x40[s.charAt(j)-'0'][i*5+1]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print third part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<24; i++)
printD(Arial24x40[s.charAt(j)-'0'][i*5+2]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print fourth part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<24; i++)
printD(Arial24x40[s.charAt(j)-'0'][i*5+3]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
// print fifth part/row of the character(s)
for (j=0; j<s.length(); j++) {
for (i=0; i<24; i++)
printD(Arial24x40[s.charAt(j)-'0'][i*5+4]);
printD(0x00); //put a distance of one pixel between the characters
}
text__continue_cursor_to_end_of_row(s,font_size);
} else
text("",font_size); // since this Arial font size only has numbers included, so instead of displaying an error-text, we display nothing
}
} else
text__continue_cursor_to_end_of_row("",font_size);
}
/*
* After printing a string (or if no string is given (text(""))), put the
* cursor at the end of that row so that a next call of text() starts
* at the beginning of the next row.
*/
void SSD1306::text__continue_cursor_to_end_of_row(String s, uint8_t font_size) {
if(font_size == 3) {
width = 24;
rows = 5;
} else if(font_size == 2) {
width = 16;
rows = 3;
} else if(font_size == 1) {
width = 11;
rows = 2;
} else if(font_size == 0) {
width = 5;
rows = 1;
}
if(s.length() > 0)
for(i2=0; i2<128 - width * s.length() - s.length(); ++i2)
printD(0x00);
else
for(i2=0; i2<128 * rows; ++i2)
printD(0x00);
}
SSD1306_OLED_5x8_11x16_16x24_24x36_fonts.ino
//#include "Energia.h"
//#include <msp430g2553.h>
#include "SSD1306.h"
SSD1306 myOLED(BIT6, // "#define BIT6 (0x0040)" = 01000000
BIT7 // "#define BIT7 (0x0080)" = 10000000
);
uint32_t i=0;
char str[42];
void setup(void){
//WDTCTL = WDTPW + WDTHOLD; // If this is enabled, the OLED won't update.
myOLED.begin(0x50, // contrast from 0x00 to 0xff (0~255)
false // inverse display
);
}
void loop() {
myOLED.printS();
// Number of text() calls: The sum of font size heights must be 64.
sprintf(str, "%lu", ++i);
/*myOLED.text(str,2); // 3 rows == x24 font size
myOLED.text("----Hello World !----",0); // 1 row == x 8 font size
myOLED.text(str,1); // 2 rows == x16 font size
myOLED.text("---------------------",0); // 1 row == x 8 font size
myOLED.text(str,0); // 1 row == x 8 font size
// 8 rows == 64 pixels*/
myOLED.text(str,3); // x40 pixels
myOLED.text(str,2); // x24 pixels
//= 64 pixels
myOLED.printE();
delay(10); // update OLED every 100 milliseconds
}
