GCC Code Coverage Report


Directory: ./
File: oled/SSD1306DisplayDriver.cpp
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 66 104 63.5%
Functions: 16 17 94.1%
Branches: 30 118 25.4%

Line Branch Exec Source
1 #include "fpp-pch.h"
2 #include <cstdint>
3 #include <cstring>
4
5 #include "DisplayDriver.h"
6 #include "I2C.h"
7 #include "RobotoFont-14.h"
8 #include "SSD1306_OLED.h"
9 #include "../common.h"
10 #include "../log.h"
11 #include <chrono>
12 #include <thread>
13
14 extern I2C_DeviceT I2C_DEV_2;
15 #if defined(PLATFORM_BBB) || defined(PLATFORM_BB64)
16 #include "util/BBBUtils.h"
17 #define I2C_DEV_PATH I2C_DEV2_PATH
18 #elif defined(PLATFORM_PI)
19 #define I2C_DEV_PATH I2C_DEV1_PATH
20 #else
21 #define I2C_DEV_PATH I2C_DEV0_PATH
22 #endif
23
24 12 SSD1306DisplayDriver::SSD1306DisplayDriver(int lt) :
25 12 DisplayDriver(lt) {
26 12 LED_DISPLAY_WIDTH = 128;
27 12 LED_DISPLAY_HEIGHT = 64;
28
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (ledType == 3 || ledType == 4) {
29 ✗ LED_DISPLAY_HEIGHT = 32;
30
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 } else if (ledType == 9 || ledType == 10) {
31 ✗ LED_DISPLAY_HEIGHT = 128;
32 ✗ LED_DISPLAY_TYPE = LED_DISPLAY_TYPE_SSD1327;
33
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 } else if (ledType == 34 || ledType == 35) {
34 ✗ LED_DISPLAY_HEIGHT = 128;
35 ✗ LED_DISPLAY_TYPE = LED_DISPLAY_TYPE_SH1107;
36 }
37
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (ledType == 5 || ledType == 6) {
38 ✗ LED_DISPLAY_TYPE = LED_DISPLAY_TYPE_SH1106;
39 }
40 12 }
41 48 SSD1306DisplayDriver::~SSD1306DisplayDriver() {
42 48 }
43 156 int SSD1306DisplayDriver::getWidth() {
44 156 return LED_DISPLAY_WIDTH;
45 }
46 172 int SSD1306DisplayDriver::getHeight() {
47 172 return LED_DISPLAY_HEIGHT;
48 }
49
50 // fppoled starts from sysinit.target, before udev/modules-load has created the
51 // i2c device nodes, so the first open of the display bus failed at every boot
52 // and the panel only came up on the retry after cape detection. Wait for the
53 // node instead: load i2c-dev ourselves (usually enough on its own, ~100ms)
54 // and poll for up to 30s so a slow boot is covered without blocking forever
55 // on a box that has no I2C at all.
56 12 static void waitForI2CDevice(const char* path) {
57
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (FileExists(path)) {
58 12 return;
59 }
60 ✗ LogInfo(VB_GENERAL, "Waiting for %s to appear\n", path);
61 ✗ system("/sbin/modprobe i2c-dev > /dev/null 2>&1");
62 ✗ for (int i = 0; i < 300 && !FileExists(path); i++) {
63 ✗ std::this_thread::sleep_for(std::chrono::milliseconds(100));
64 }
65 ✗ if (!FileExists(path)) {
66 ✗ LogWarn(VB_GENERAL, "%s did not appear within 30s\n", path);
67 }
68 }
69
70 12 bool SSD1306DisplayDriver::initialize(int& i2cBus) {
71 12 waitForI2CDevice(I2C_DEV_PATH);
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (init_i2c_dev2(I2C_DEV_PATH, SSD1306_OLED_ADDR) != 0) {
73 ✗ LogErr(VB_GENERAL, "(Main)i2c: could not open %s for the display at 0x%02x\n", I2C_DEV_PATH, SSD1306_OLED_ADDR);
74 ✗ return false;
75 }
76
3/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
12 if (ledType && display_Init_seq()) {
77 #ifdef PLATFORM_BBB
78 // was not able to configure the led on I2C2, lets see if
79 // it's available on I2C1
80 ✗ Close_device(I2C_DEV_2.fd_i2c);
81 ✗ if (getBeagleBoneType() == BeagleBoneType::PocketBeagle) {
82 ✗ PinCapabilities::getPinByName("P2-09").configPin("i2c");
83 ✗ PinCapabilities::getPinByName("P2-11").configPin("i2c");
84 } else {
85 ✗ PinCapabilities::getPinByName("P9-17").configPin("i2c");
86 ✗ PinCapabilities::getPinByName("P9-18").configPin("i2c");
87 }
88
89 ✗ if (init_i2c_dev2(I2C_DEV1_PATH, SSD1306_OLED_ADDR) != 0) {
90 ✗ LogErr(VB_GENERAL, "(Main)i2c1: OOPS! Something Went Wrong\n");
91 ✗ return false;
92 }
93 ✗ if (display_Init_seq()) {
94 ✗ LogErr(VB_GENERAL, "Could not initialize display\n");
95 ✗ return false;
96 }
97 #else
98 ✗ LogErr(VB_GENERAL, "Could not initialize display\n");
99 ✗ return false;
100 #endif
101 }
102 12 i2cBus = I2C_DEV_2.i2c_dev_path[strlen(I2C_DEV_2.i2c_dev_path) - 1] - '0';
103 12 setTextSize(1);
104
6/12
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
12 if (ledType == 2 || ledType == 4 || ledType == 6 || ledType == 8 || ledType == 10 || ledType == 35) {
105 ✗ ::setRotation(2);
106
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 } else if (ledType == 32 || ledType == 33) {
107 ✗ ::setRotation(1);
108
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 } else if (ledType) {
109 12 ::setRotation(0);
110 }
111
112 12 return true;
113 }
114
115 151 void SSD1306DisplayDriver::printString(int x, int y, const std::string& str, bool white) {
116
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 7 times.
151 setTextColor(white ? WHITE : BLACK);
117 151 setCursor(x, y);
118 151 print_str(str.c_str());
119 151 }
120 7 void SSD1306DisplayDriver::printStringCentered(int y, const std::string& str, bool white) {
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 setTextColor(white ? WHITE : BLACK);
122 7 int len = getTextWidth(str.c_str());
123 7 len /= 2;
124 7 setCursor(64 - len, y);
125 7 print_str(str.c_str());
126 7 }
127 7 void SSD1306DisplayDriver::fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, bool white) {
128
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 ::fillTriangle(x0, y0, x1, y1, x2, y2, white ? WHITE : BLACK);
129 7 }
130 52 void SSD1306DisplayDriver::drawLine(short x0, short y0, short x1, short y1, bool white) {
131
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 ::drawLine(x0, y0, x1, y1, white ? WHITE : BLACK);
132 52 }
133 56 void SSD1306DisplayDriver::drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, bool white) {
134
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 ::drawBitmap(x, y, bitmap, w, h, white ? WHITE : BLACK);
135 56 }
136 7 void SSD1306DisplayDriver::drawRect(short x0, short y0, short x1, short y1, bool white) {
137
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 ::drawRect(x0, y0, x1, y1, white ? WHITE : BLACK);
138 7 }
139 14 void SSD1306DisplayDriver::fillRect(short x0, short y0, short x1, short y1, bool white) {
140
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 ::fillRect(x0, y0, x1, y1, white ? WHITE : BLACK);
141 14 }
142 71 void SSD1306DisplayDriver::clearDisplay() {
143 71 ::clearDisplay();
144 71 }
145 71 void SSD1306DisplayDriver::flushDisplay() {
146 71 ::Display();
147 71 }
148 12 void SSD1306DisplayDriver::displayOff() {
149 12 ::clearDisplay();
150 12 ::Display();
151 12 }
152 ✗ bool SSD1306DisplayDriver::setFont(const std::string& f) {
153 ✗ if (f == "") {
154 ✗ setTextFont(nullptr);
155 ✗ return true;
156 }
157 ✗ if (f == "Roboto_Medium_14") {
158 ✗ setTextFont(&Roboto_Medium_14);
159 ✗ return true;
160 }
161 ✗ return false;
162 }
163