Help with understaning display code with buffers

I have an erm12864 display which uses the uc1609 chip, so i was checking out example codes and they use buffers(buffers act as storage when data is sent from the uc to the display chip?) which i've never used and pointers,

#include <ERM19264_UC1609.h>

#define mylcdheight 64
#define mylcdwidth  192
#define VbiasPOT 0x49 //Constrast 00 to FE , 0x49 is default. USER adjust.

// GPIO 5-wire SPI interface
#define CD 10 // GPIO pin number pick any you want 
#define RST 8 // GPIO pin number pick any you want
#define CS 9  // GPIO pin number pick any you want
// GPIO pin number SCK(UNO 13) , HW SPI , SCK
// GPIO pin number SDA(UNO 11) , HW SPI , MOSI

ERM19264_UC1609  mylcd(CD, RST, CS); // instate object , CD, RST, CS

// vars for the test
static long previousMillis  = 0;
uint16_t count  = 0;
uint16_t seconds  = 0;
bool colour = false;

// ************* SETUP ***************
void setup() {
  mylcd.LCDbegin(VbiasPOT); // initialize the LCD
  mylcd.LCDFillScreen(0x00, 0);
}

// *********** MAIN LOOP ******************
void loop() {
  static long framerate = 0;

  mylcd.setTextColor(FOREGROUND);
  mylcd.setTextSize(1);
  uint8_t  screenBuffer[768];

  MultiBuffer left_side;
  left_side.screenbitmap = (uint8_t*) &screenBuffer;
  left_side.width = (mylcdwidth / 2) ; //96
  left_side.height = mylcdheight;
  left_side.xoffset = 0;
  left_side.yoffset = 0;


  MultiBuffer right_side;
  right_side.screenbitmap = (uint8_t*) &screenBuffer;
  right_side.width = (mylcdwidth / 2); //96
  right_side.height = mylcdheight;
  right_side.xoffset = (mylcdwidth / 2); //96
  right_side.yoffset = 0;

  while(1)
  {
    display_Left(&left_side, framerate, count);
    display_Right(&right_side);
    framerate++;
    count++;
  }
}
// *********** END OF MAIN ***********

// Function to display left hand side buffer
void display_Left(MultiBuffer* targetbuffer, long currentFramerate, int count)
{
  mylcd.ActiveBuffer = targetbuffer; // set target buffer object
  mylcd.LCDclearBuffer();
  mylcd.setCursor(0, 0);
  mylcd.print(F("Left Buffer:"));

  mylcd.setCursor(0, 10);
  mylcd.print(F("96 * 64/8 = 768"));

  mylcd.setCursor(0, 20);
  mylcd.print(seconds);

  mylcd.setCursor(0, 30);
  mylcd.print(count);
  // Values to count frame rate per second
  static long lastFramerate = 0;
  static uint16_t fps;
  unsigned long currentMillis = millis();

  if (currentMillis  - previousMillis  >= 1000) {
    fps = currentFramerate - lastFramerate;
    lastFramerate = currentFramerate ;
    previousMillis  = currentMillis;
    colour =  !colour;
    seconds++;
  }

  mylcd.setCursor(0, 40);
  mylcd.print(fps);

  mylcd.setCursor(0, 50);
  mylcd.print("V 1.2.0");
  mylcd.drawFastVLine(92, 0, 63, FOREGROUND);
  mylcd.LCDupdate();
}

// Function to display right hand side buffer
void display_Right(MultiBuffer* targetbuffer)
{
  mylcd.ActiveBuffer = targetbuffer; // set target buffer object
  mylcd.LCDclearBuffer();
  mylcd.setCursor(0, 0);
  mylcd.print(F("Right buffer:"));

  mylcd.fillRect(0, 10, 20, 20, colour);
  mylcd.fillCircle(40, 20, 10, FOREGROUND);
  mylcd.fillTriangle(60, 30, 70, 10, 80, 30, !colour);
  mylcd.drawRoundRect(10, 40, 60, 20, 10, FOREGROUND);

  mylcd.LCDupdate();
}

So in void loop we declare left side and right side size, offset and make a pointer to screenbuffer, which i don't even know what is it used for, clearing the display?
Then while(1) is just making it loop?
and it points to left and right side buffer and includes 2 variables in displayLeft function?
Then in function display_Left i don't quite understand what MultiBuffer* targetbuffer does, and what about those variables they aren't global, they are private right?
In a code i have a separate function that measures temperature and returns measuredTemperature, how would i make it that it prints it to the display?, i tried couple different things but none of them worked, would i need to add it in the function that calls the display_Left function?
And also i use millis instead of delay but then it doesn't display the text so i have put it in function loop without any delay whatsoever, not sure why
Hope you understood anything from what i just wrote :sweat_smile:
would appreciate a short explanation to this code, also read guides on the internet about pointers and functions... to make it a bit easier to understand on my own

I am sure that your #include <ERM19264_UC1609.h> works.
But it looks painful. I have never seen such a complex buffer arrangement.

I strongly advise using U8g2lib. It supports UC1609 and has a choice of constructors with different buffer sizes.

Most importantly, many people use U8g2. You can change to a different controller by simply using a different constructor.
You need to use a paged buffer for a Uno because the SRAM is pretty small.
On a MEGA2560 you can afford to have a full size buffer.

David.

It is an area of memory used for gathering the bit pattern of your display prior to transferring the data to your display. You see the displays can’t be read, and on a display you might want to draw say two overlapping shapes. This involves setting the pixels for one shape and then setting the pixels for another. The way the pixels are represented in the display are as bits. So to make a specific bit into a one without altering the other bits in the display, you have to read what is there already and apply bit wise operations so you only change the bits for the shape you are currently drawing.

As you can’t read the display you have to do that in an area of memory we call a buffer. Then when the buffer is filled with the image you transfer it into the display. Note how you do all your drawing and then call a show or display function.

Now the best way to do this is to have a buffer the same size as your display screen, but as that uses a lot of memory you can cut down on the buffer size to say a quarter of the display. This uses less memory in the Arduino but the price you pay is you have to draw your display four times, transferring it to the appropriate part of the screen for each draw. So you save memory at the expense of a slower display update.

A pointer is simply a variable which holds not a value, but the address of where that value or buffer memory is to be found. It is denoted by a * immediately before the variable name.

I hope that has given you a handel on what is going on with your code.

1 Like

Yeah i wanted to use it but i get this error and i don't know what's wrong

/tmp/cc6WfwXE.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_main.cpp.o.13284':
<artificial>:(.text.startup+0x66): undefined reference to `u8x8_d_uc1609_slg19264'
<artificial>:(.text.startup+0x68): undefined reference to `u8x8_d_uc1609_slg19264'
<artificial>:(.text.startup+0xa2): undefined reference to `u8x8_d_uc1609_slg19264'
collect2: error: ld returned 1 exit status
*** [.pio/build/nanoatmega328/firmware.elf] Error 1

maybe something wrong with display definitions

Yes thanks for the explanation, now i understand a bit more,
but why does the code uses 2 buffers for left and right side?
I don't see anyway how that would save on flash, exceot maybe the area of memory is smaller because it's separated for left and right side?

Correct it wouldn’t seem to save anything.

Don’t always assume the writer of code on the internet knows what he is doing, or wants to minimise memory usage. Maybe they had some special reason for doing this. Maybe a speed consideration if one side changed more rapidly than the other.

Ah ok, otherwise there is nothing wrong with just using a single buffer?

Correct.