Advanced OLED Display Development Using the wiringOP Library on OrangePi ZERO 2
This section focuses on extending the functionality of OLED displays through custom applications built on the wiringOP library. The process involves utilizing specific API functions to create text and graphical outputs.
Text Rendering with the oled_putstr Function
To display text, implement a program structure similar to the demo code, with the core logic placed in a dedicated function. Here is a revised example:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <wiringPi.h>
#include "oled.h"
#include "font.h"
void renderText(struct display_info *screen) {
// Text rendering logic goes here
}
int main(int argc, char **argv) {
int status;
char devicePath[32];
struct display_info screen;
if (argc < 2) {
printf("\nUsage:\n%s <I2C bus device node>\n", argv[0]);
return -1;
}
memset(&screen, 0, sizeof(screen));
snprintf(devicePath, sizeof(devicePath), "%s", argv[1]);
screen.address = OLED_I2C_ADDR;
screen.font = font2;
status = oled_open(&screen, devicePath);
if (status < 0) {
printf("\nERROR: %d, Failed to open OLED\n\n", status);
} else {
status = oled_init(&screen);
if (status < 0) {
printf("\nERROR: %d, Failed to initialize OLED\n\n", status);
} else {
printf("---------start--------\n");
oled_clear(&screen);
renderText(&screen);
delay(3000);
oled_clear(&screen);
printf("----------end---------\n");
}
}
return 0;
}
The font2 type is often preferred for its readability, supporting up to 21 characters per line with adequate spacing. Other fonts like font1 and font3 allow 25 characters per line but may appear cramped, with font3 being particularly small and less legible.
The oled_putstr function operates in page-addressing mode, displaying a string on a single page. If the string exceeds the page's capacity, only the initial characters are shown. For example, to display content on the third page:
void renderText(struct display_info *screen) {
uint8_t textData[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
oled_putstr(screen, 3, textData);
oled_send_buffer(screen);
}
To repeat the same text across multiple pages, use a loop:
void renderText(struct display_info *screen) {
uint8_t textData[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int pageIndex = 0; pageIndex < 8; pageIndex++) {
oled_putstr(screen, pageIndex, textData);
}
oled_send_buffer(screen);
}
For displaying longer passgaes, offset the array pointer to manage text across pages:
void renderText(struct display_info *screen) {
uint8_t textData[] = " Life is like a rainbow, "
"each color represents a different experience, "
"and together they make up the beautiful sky.";
for (int pageIndex = 0; pageIndex < 6; pageIndex++) {
oled_putstr(screen, pageIndex + 1, textData + pageIndex * 21);
}
oled_send_buffer(screen);
}
Graphics Generation with the oled_putpixel Function
The oled_putpixel function enables pixel-level control, allowing for the creation of custom grahpics. This is commonly achieved using algorithms like Bresenham's for efficient rendering.
Drawing Lines
Implement a line-drawing function using Bresenham's algorithm to connect two points on the OLED grid:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <wiringPi.h>
#include <math.h>
#include "oled.h"
#include "font.h"
void drawLineSegment(struct display_info *screen, int startX, int startY, int endX, int endY) {
int deltaX = abs(endX - startX);
int deltaY = abs(endY - startY);
int stepX = (startX < endX) ? 1 : -1;
int stepY = (startY < endY) ? 1 : -1;
int error = deltaX - deltaY;
while (startX != endX || startY != endY) {
oled_putpixel(screen, startX, startY, 1);
oled_send_buffer(screen);
int doubleError = 2 * error;
if (doubleError > -deltaY) {
error -= deltaY;
startX += stepX;
}
if (doubleError < deltaX) {
error += deltaX;
startY += stepY;
}
}
}
int main(int argc, char **argv) {
int status;
char devicePath[32];
struct display_info screen;
if (argc < 2) {
printf("\nUsage:\n%s <I2C bus device node>\n", argv[0]);
return -1;
}
memset(&screen, 0, sizeof(screen));
snprintf(devicePath, sizeof(devicePath), "%s", argv[1]);
screen.address = OLED_I2C_ADDR;
screen.font = font2;
status = oled_open(&screen, devicePath);
if (status < 0) {
printf("\nERROR: %d, Failed to open OLED\n\n", status);
} else {
status = oled_init(&screen);
if (status < 0) {
printf("\nERROR: %d, Failed to initialize OLED\n\n", status);
} else {
printf("---------start--------\n");
oled_clear(&screen);
drawLineSegment(&screen, 0, 50, 100, 0);
delay(3000);
oled_clear(&screen);
printf("----------end---------\n");
}
}
return 0;
}
Drawing Circles
Similarly, circles can be drawn using Bresenham's algorithm for circles. Here is a basic implementation:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <wiringPi.h>
#include "oled.h"
#include "font.h"
void drawCircleShape(struct display_info *screen, int centerX, int centerY, int radius) {
int x = radius;
int y = 0;
int decision = 1 - radius;
while (x >= y) {
oled_putpixel(screen, centerX + x, centerY + y, 1);
oled_putpixel(screen, centerX - x, centerY + y, 1);
oled_putpixel(screen, centerX + x, centerY - y, 1);
oled_putpixel(screen, centerX - x, centerY - y, 1);
oled_putpixel(screen, centerX + y, centerY + x, 1);
oled_putpixel(screen, centerX - y, centerY + x, 1);
oled_putpixel(screen, centerX + y, centerY - x, 1);
oled_putpixel(screen, centerX - y, centerY - x, 1);
oled_send_buffer(screen);
y++;
if (decision <= 0) {
decision += 2 * y + 1;
} else {
x--;
decision += 2 * (y - x) + 1;
}
}
}