U8g2: Graphics Library for Monochrome OLEDs and LCDs

A question for you Oliver, if I may.

I have a ks0108 based 128x64 glcd. I would like to connect it to an esp8266. Obviously, shortage of pins is the first problem. But I have solved that part using 2 x 74hc595. One shift register drives the D0-D7 data lines and the other register drives the RS, CS1 & CS2. The Enable pin is driven directly by an esp output pin, and the 2 registers are daisy chained to the SPI pins on the esp. It works, displaying some simple test patterns. I may try using some of the remaining register outputs to control the backlight level.

So my question is, how difficult would it be for me to modify u8g2 to use this setup? I'm sure I could write some code to take an image of the screen held in ram and transmit that via the registers to the display. Where would I plug that code into the library, if possible?

I am sure that you could get this to work. But it seems a lot of effort.

An ST7920 display looks very similar to the KS0108 style of 128x64 monichrome.
You can operate it by SPI. The only problem is that most Ebay ST7920 modules are 5V. You would need to put a potential divider on the MISO pin.

You either read the KS0108 GRAM or you maintain a mirror image in your own RAM.
I am not sure whether you can load the 595 pins in parallel before shifting out by SPI.

David.

Edit. The HC595 is output-only. You would be better off with a Port Expander chip like a MCP23S17 (or MCP23017 I2C version)

any chance m2tklib porting is still in the works?

Thanks for replying, David!

david_prentice:
I am sure that you could get this to work. But it seems a lot of effort.

Well, that's why I'm asking. It would be a shame to waste the display and I have no other use for it at the moment.

david_prentice:
An ST7920 ... You would need to put a potential divider on the MISO pin... The HC595 is output-only. You would be better off with a Port Expander chip like a MCP23S17 (or MCP23017 I2C version)

I don't see the value in being able to read from the display. With 8-bit AVR chips that don't have much ram, I get it, but esp has loads.

david_prentice:
I am not sure whether you can load the 595 pins in parallel before shifting out by SPI.

You can't. As you say, the 595 is serial-in to parallel-out only.

I did also consider using 2 x pcf8475, which are i2c, and then replacing my Wemos Mini with one of several esp-01 modules I have gathering dust in a box, for the final version.

I have a couple of KS0108. I don't think that I have done anything with them recently. They use up lots of GPIO.

Yes, not much point in doing RMW when you have plenty of RAM for a screen buffer.
I would either use a ST7920 or an TFT or OLED with SPI interface. The TFT is a lot more attractive.

From memory, you need 5 control lines with 8 data lines. The 595s can reduce your pin count. I would keep a GPIO for the strobe. Otherwise you have to shift another 16 bits for each wobble.

I wish everyone laid out their breadboards neatly. It makes all the difference.

David.

jptheripper:
any chance m2tklib porting is still in the works?

Well, workload does not allow me to work much on this, but yes, this is planned.
However I can not tell, when this will be there.

Oliver

PaulRB:
A question for you Oliver, if I may.

I have a ks0108 based 128x64 glcd. I would like to connect it to an esp8266. Obviously, shortage of pins is the first problem. But I have solved that part using 2 x 74hc595. One shift register drives the D0-D7 data lines and the other register drives the RS, CS1 & CS2. The Enable pin is driven directly by an esp output pin, and the 2 registers are daisy chained to the SPI pins on the esp. It works, displaying some simple test patterns. I may try using some of the remaining register outputs to control the backlight level.

So my question is, how difficult would it be for me to modify u8g2 to use this setup? I'm sure I could write some code to take an image of the screen held in ram and transmit that via the registers to the display. Where would I plug that code into the library, if possible?

Definitly possible.

Option 1 (high speed solution):

You change procedure u8x8_byte_ks0108 (and u8x8_byte_set_ks0108_cs) in this file:

Basically, any calls to
u8x8_gpio_call()
has to be replaced by a custom function, which would set the pin through your 595.

Option 2 (low speed solution):
You keep the u8x8_byte_ks0108() procedure as it is, und just change the function which is called by u8x8_gpio_call().
This gpio call() will finally call the function u8x8_gpio_and_delay_arduino() in

In that procedure, you have to wait for the following signals:
U8X8_MSG_GPIO_CS1
U8X8_MSG_GPIO_CS2
U8X8_MSG_GPIO_D0 .. U8X8_MSG_GPIO_D7
U8X8_MSG_GPIO_E
U8X8_MSG_GPIO_DC
and, once received, set the level of that pin to the value provided in "arg_int"
Of course the new procedure has to support the delay procedures.

Oliver

david_prentice:
I am sure that you could get this to work. But it seems a lot of effort.

Agree. There are good displays available for a small amount of money.
You could have a look at my gallery page here to get some ideas on these displays:

All of the displays are available on some internet marketplaces or from typical electronic stores.

david_prentice:
Edit. The HC595 is output-only. You would be better off with a Port Expander chip like a MCP23S17 (or MCP23017 I2C version)

U8g2 does not read data from any display.

Oliver

Thanks for the reply Oliver, much appreciated.

olikraus:
Option 1 (high speed solution):

You change procedure u8x8_byte_ks0108 (and u8x8_byte_set_ks0108_cs) in this file:
u8g2/csrc/u8x8_byte.c at master · olikraus/u8g2 · GitHub

Basically, any calls to
u8x8_gpio_call()
has to be replaced by a custom function, which would set the pin through your 595.

Just those two functions? Great!

So...

void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg)
{
  u8x8_gpio_SetCS(u8x8, arg&1);
  arg = arg >> 1;
  u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS1, arg&1);
  arg = arg >> 2;
  u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS2, arg&2);
}

This code just sets the CS1 & CS2 pins. But reading the code, I can't figure out which bits in arg do what.

Bit 0 of arg seems to be some kind of overall Chip Select pin. Is that irrelevant for KS0108, because it has CS1 & CS2?

Bit 1 of arg sets CS1. Easy.

But it looks like Bit 4 of arg sets CS2? arg gets shifted right by 3 bits, then bit 1 is masked.

Does Bit 3 of arg do anything?

uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t i, b;
  uint8_t *data;
 
  switch(msg)
  {
    case U8X8_MSG_BYTE_SEND:
      data = (uint8_t *)arg_ptr;
      while( arg_int > 0 )
      {
 b = *data;
 data++;
 arg_int--;
 for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
 {
  u8x8_gpio_call(u8x8, i, b&1);
  b >>= 1;
 }    
 
 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
 u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
 u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
      }
      break;
      
    case U8X8_MSG_BYTE_INIT:
      /* disable chipselect */
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);    
      /* ensure that the enable signal is low */
      u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
      break;
    case U8X8_MSG_BYTE_SET_DC:
      u8x8_gpio_SetDC(u8x8, arg_int);
      break;
    case U8X8_MSG_BYTE_START_TRANSFER:
      /* expects 3 bits in arg_int for the chip select lines */ 
      u8x8_byte_set_ks0108_cs(u8x8, arg_int);
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
      break;
    case U8X8_MSG_BYTE_END_TRANSFER:
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
      u8x8_byte_set_ks0108_cs(u8x8, arg_int);
      break;
    default:
      return 0;
  }
  return 1;
}

I have to modify the above to send bytes to the display via the registers. I think I understand what I need to do for message U8X8_MSG_BYTE_SEND, which is the most complex. For U8X8_MSG_BYTE_INIT and U8X8_MSG_BYTE_SET_DC, there is not much to be done. For U8X8_MSG_BYTE_START_TRANSFER and U8X8_MSG_BYTE_END_TRANSFER, I can't figure out what, if anything, I need to do. Can I leave those as-is?

Here is my test code which produced the pattern shown in the picture above, in case it is important. It's very short.

#include <SPI.h>

// D5 and D7 used as SPI bus to drive 2 x 74hc595 Shift Registers
SPISettings sn74hc595(100000000UL, MSBFIRST, SPI_MODE0);
#define LATCH D8

//Shift register pins controlling KS0108 Graphic LCD
// GLCD_RS: H = data, L = instruction
#define GLCD_E   D0

#define GLCD_RS  6
#define GLCD_CS1 5
#define GLCD_CS2 7

byte control = 0;

void sendGLCD(byte data) { //Send a byte to the GLCD
  digitalWrite(GLCD_E, HIGH);
  digitalWrite(LATCH, LOW);
  SPI.transfer(control);
  SPI.transfer(data);
  digitalWrite(LATCH, HIGH);
  digitalWrite(GLCD_E, LOW);
  delayMicroseconds(5);
}

void setup() {
  SPI.begin();
  pinMode(LATCH, OUTPUT);
  pinMode(GLCD_E, OUTPUT);

  bitSet(control, GLCD_CS1);
  bitSet(control, GLCD_CS2);
  bitClear(control, GLCD_RS);

  SPI.beginTransaction(sn74hc595);
  sendGLCD(0b00111111); // Enable display
  sendGLCD(0b11000000); // Set Scroll Position = 0
  SPI.endTransaction();


}

byte i = 0;

void loop() {

  SPI.beginTransaction(sn74hc595);
  for (int x = 0; x < 8; x++) {
    bitSet(control, GLCD_CS1);
    bitSet(control, GLCD_CS2);
    bitClear(control, GLCD_RS);
    sendGLCD(0b10111000 | x); // set X
    sendGLCD(0b01000000); // Set Y = 0
    bitSet(control, GLCD_RS);
    bitSet(control, GLCD_CS1);
    bitClear(control, GLCD_CS2);
    for (int y = 0; y < 128; y++) {
      if (y == 64) {
        bitClear(control, GLCD_CS1);
        bitSet(control, GLCD_CS2);
      }
      sendGLCD(i++);
    }
  }
  SPI.endTransaction();
  delay(500);
  i++;
}

So here is my attempt:

byte control = 0;

void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg)
{
  u8x8_gpio_SetCS(u8x8, arg&1);
  arg = arg >> 1;
  //u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS1, arg&1);
  bitWrite(control, GLCD_CS1, arg&1);
  arg = arg >> 2;
  //u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS2, arg&2);
  bitWrite(control, GLCD_CS2, arg&2);
}
uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  uint8_t i, b;
  uint8_t *data;
 
  switch(msg)
  {
    case U8X8_MSG_BYTE_SEND:
      data = (uint8_t *)arg_ptr;
      SPI.beginTransaction(sn74hc595);
      while( arg_int > 0 )
      {
	b = *data;
	data++;
	arg_int--;
        //for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
	//{
	//  u8x8_gpio_call(u8x8, i, b&1);
	//  b >>= 1;
	//}    

        digitalWrite(LATCH, LOW);
        SPI.transfer(control);
        SPI.transfer(b);
        digitalWrite(LATCH, HIGH);

	u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
	//u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
        digitalWrite(GLCD_E, HIGH);
	u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
	//u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
        digitalWrite(GLCD_E, LOW);
      }
      SPI.endTransaction();
      break;
      
    case U8X8_MSG_BYTE_INIT:
      /* disable chipselect */
      u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);    
      /* ensure that the enable signal is low */
      //u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
      digitalWrite(GLCD_E, LOW);
      break;
    case U8X8_MSG_BYTE_SET_DC:
      //u8x8_gpio_SetDC(u8x8, arg_int);
      bitWrite(control, GLCD_RS, arg_int);
      break;
    case U8X8_MSG_BYTE_START_TRANSFER:
      /* expects 3 bits in arg_int for the chip select lines */ 
      u8x8_byte_set_ks0108_cs(u8x8, arg_int);
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
      break;
    case U8X8_MSG_BYTE_END_TRANSFER:
      u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
      u8x8_byte_set_ks0108_cs(u8x8, arg_int);
      break;
    default:
      return 0;
  }
  return 1;
}

I have not attempted to compile or test this. I wanted to see if I was "in the ball park" first, or if I am missing anything else I need to change.

Thanks for your help!

But it looks like Bit 4 of arg sets CS2? arg gets shifted right by 3 bits, then bit 1 is masked.

Does Bit 3 of arg do anything?

Oh, bug. It should be "&1".

I will create an issue for this:

Oliver

For U8X8_MSG_BYTE_INIT and U8X8_MSG_BYTE_SET_DC, there is not much to be done. For U8X8_MSG_BYTE_START_TRANSFER and U8X8_MSG_BYTE_END_TRANSFER, I can't figure out what, if anything, I need to do. Can I leave those as-is?

You can ignore SET_DC, but you have to set the CS line correctly with START_TRANSFER and END_TRANSFER.
The variable "arg_int" will tell you which KS0108 should be activated.
bit 0 in arg_int: CS (there is not CS0, i rejust the CS signal from other devices)
bit 1 in arg_int: CS1
bit 2 in arg_int: CS2 (in general this can be ignored for any 128x64 display)

The new byte function already looks good.

Olive

olikraus:
You can ignore SET_DC, but you have to set the CS line correctly with START_TRANSFER and END_TRANSFER.

But there is no CS line, with KS0108 there is CS1 and CS2 for the two halves of the display, as you go on to say:

olikraus:
The variable "arg_int" will tell you which KS0108 should be activated.
bit 0 in arg_int: CS (there is not CS0, i rejust the CS signal from other devices)
bit 1 in arg_int: CS1

I don't understand your comment here:

olikraus:
bit 2 in arg_int: CS2 (in general this can be ignored for any 128x64 display)

because CS2 controls half of a 128x64 ks0108. Or did you mean CS --> CS1 and CS1 --> CS2 on the display?

olikraus:
The new byte function already looks good.

Thanks for the encouragement, but I am struggling to get it compiled!

The directory/folder structure I downloaded from github does not seem to match the IDE's expectations. I had to copy every file from /u8g2/csrc and /u8g2/cppsrc into /u8g2 to get anywhere at all.

Here is my test sketch:

#include <Arduino.h>
#include <SPI.h>

#define GLCD_RS  6
#define GLCD_CS1 5
#define GLCD_CS2 7
#define LATCH D8

uint8_t control = 0;

SPISettings sn74hc595(100000000UL, MSBFIRST, SPI_MODE0);

#include <U8g2lib.h>

/* Constructor */
U8G2_KS0108_128X64_1 u8g2(U8G2_R0, U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE,
                                   U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE, U8X8_PIN_NONE, /*enable=*/ D0, /*dc=*/ U8X8_PIN_NONE, /*cs0=*/ U8X8_PIN_NONE, /*cs1=*/ U8X8_PIN_NONE, /*cs2=*/ U8X8_PIN_NONE, /* reset=*/  U8X8_PIN_NONE);     // Set R/W to low!

/* u8g2.begin() is required and will sent the setup/init sequence to the display */
void setup(void) {
  SPI.begin();
  pinMode(LATCH, OUTPUT);
  u8g2.begin();
}

/* draw something on the display with the `firstPage()`/`nextPage()` loop*/
void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,20,"Hello World!");
  } while ( u8g2.nextPage() );
  delay(1000);
}

and attached is my modified u8x8_byte.c

As you can see, I was forced to repeat some #includes and #defines in there, but now I get the following messages:

Arduino: 1.6.11 (Linux), Board: "WeMos D1 R2 & mini, 80 MHz, 921600, 4M (3M SPIFFS)"

WARNING: Category '' in library UIPEthernet is not valid. Setting to 'Uncategorized'
In file included from /home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:1:0:
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:44:1: error: unknown type name 'class'
 class SPISettings {
 ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:44:19: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
 class SPISettings {
                   ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:53:1: error: unknown type name 'class'
 class SPIClass {
 ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:53:16: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
 class SPIClass {
                ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:82:1: error: unknown type name 'SPIClass'
 extern SPIClass SPI;
 ^
In file included from /home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:24:0,
                 from /home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:1:
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c: In function 'u8x8_byte_set_ks0108_cs':
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:324:12: error: 'control' undeclared (first use in this function)
   bitWrite(control, GLCD_CS1, bitRead(arg, 2));
            ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/Arduino.h:172:30: note: in definition of macro 'bitSet'
 #define bitSet(value, bit) ((value) |= (1UL << (bit)))
                              ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:324:3: note: in expansion of macro 'bitWrite'
   bitWrite(control, GLCD_CS1, bitRead(arg, 2));
   ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:324:12: note: each undeclared identifier is reported only once for each function it appears in
   bitWrite(control, GLCD_CS1, bitRead(arg, 2));
            ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/Arduino.h:172:30: note: in definition of macro 'bitSet'
 #define bitSet(value, bit) ((value) |= (1UL << (bit)))
                              ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:324:3: note: in expansion of macro 'bitWrite'
   bitWrite(control, GLCD_CS1, bitRead(arg, 2));
   ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c: In function 'u8x8_byte_ks0108':
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:340:10: error: request for member 'beginTransaction' in something not a structure or union
       SPI.beginTransaction(sn74hc595);
          ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:340:28: error: 'sn74hc595' undeclared (first use in this function)
       SPI.beginTransaction(sn74hc595);
                            ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:352:12: error: request for member 'transfer' in something not a structure or union
         SPI.transfer(control);
            ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:352:22: error: 'control' undeclared (first use in this function)
         SPI.transfer(control);
                      ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:353:12: error: request for member 'transfer' in something not a structure or union
         SPI.transfer(b);
            ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:361:10: error: request for member 'endTransaction' in something not a structure or union
       SPI.endTransaction();
          ^
In file included from /home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/SPI/SPI.h:24:0,
                 from /home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:1:
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:372:42: error: 'arg' undeclared (first use in this function)
       bitWrite(control, GLCD_RS, bitRead(arg, 3));
                                          ^
/home/paul/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/Arduino.h:174:41: note: in definition of macro 'bitWrite'
 #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
                                         ^
/home/paul/sketchbook/libraries/u8g2/u8x8_byte.c:372:34: note: in expansion of macro 'bitRead'
       bitWrite(control, GLCD_RS, bitRead(arg, 3));
                                  ^
exit status 1
Error compiling for board WeMos D1 R2 & mini.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

The first error, "error: unknown type name 'class'" makes me worry I am trying to mix & match c and c++ and I don't know what I am doing.

Any help would be appreciated!

u8x8_byte.c (15.7 KB)

Or did you mean CS --> CS1 and CS1 --> CS2 on the display?

Yes exactly.

The directory/folder structure I downloaded from github does not seem to match the IDE's expectations. I had to copy every file from /u8g2/csrc and /u8g2/cppsrc into /u8g2 to get anywhere at all.

You should install U8g2 from the Arduino IDE Library Manager (be sure to delete everything first). After installation, the correct structure will be here:

/Arduino/libraries/U8g2_Arduino

Oliver

Ah, I downloaded the wrong ZIP. I incorrectly downloaded this. I have now download this.

But still getting the same error messages. I think the problem is that I am trying to use the SPI library, which is C++, in a C source file.

So I think I need to make my changes in a copy of the u8x8_byte_ks0108() and u8x8_byte_set_ks0108_cs() functions in U8x8lib.cpp?

PaulRB:
So I think I need to make my changes in a copy of the u8x8_byte_ks0108() and u8x8_byte_set_ks0108_cs() functions in U8x8lib.cpp?

Yes, if you want to use digitalWrite().
Also you should declare your function in the cpp code as
extern "C" uint8_t u8x8_byte_ks0108(...);
to force this to be a C function in a C++ code.

Oliver

Thanks for your continued assistance Oliver.

I've already done as you suggested. But the compiler then complained that there were duplicate function definitions. I noticed that the alternative version of u8x8_byte_ks0108() and u8x8_byte_ks0108() in that file have slightly different names which include the word "_arduino". So I have changed the names of my versions slightly also. Now it compiles OK. But of course my versions of the functions will not be used because they are not referenced anywhere else. How is this implemented for the "_arduino" versions?

Hmm... Maybe I should just use the "_arduino" versions of the function names for my own versions. Hopefully the compiler directives that check for AVR architecture will prevent complaints about duplication because I am on esp architecture.

PaulRB:
Hmm... Maybe I should just use the "_arduino" versions of the function names for my own versions. Hopefully the compiler directives that check for AVR architecture will prevent complaints about duplication because I am on esp architecture.

Indeed I guess, this will be the most simple solution. Just remove all other existing "_arduino" versions and use your own one.

Oliver

Hi Oliver,

I have a highly optimized project that uses your u8g library with a 0.96 OLED display, and it's working great. Recently I found this topic about the u8g2 and then I decided to try porting it to this new version just to check if it could make it better in someway but I found some problems doing this.

The first problem is that I was unable to use the F() syntax with u8g2.drawStr function to store strings in flash memory rather than RAM. On u8g I use u8g.drawStr(XX, YY, F("Text")); and it works fine, but when I tried u8g2.drawStr(XX, YY, F("Text")); I receive lot of compiler errors. It only works without the syntax from the function: u8g2.drawStr(XX, YY, "Text");. Is this expected to happen?

It's not a huge problem because I changed the code to u8g2.setCursor(XX,YY); and u8g2.print(F("Text")); but this way gave me a lot of more work since I couldn't just replace the text "u8g." to "u8g2.".

The second one is about custom fonts. I found a post where you told someone how to use bdf2u8g. I followed your instructions and it worked fine, I removed unwanted characters from 3 or 4 fonts that I use to save space but I couldn't figure out how to use these fonts with u8g2. Is it possible to use them with u8g2?