For discussion - Reconfigurable OLED display alternative

This commit is contained in:
Martin Budden 2017-06-25 13:30:17 +01:00
parent 14f82e2a63
commit 82be9ecd78
11 changed files with 215 additions and 165 deletions

View File

@ -107,7 +107,8 @@
#define PG_SONAR_CONFIG 516 #define PG_SONAR_CONFIG 516
#define PG_ESC_SENSOR_CONFIG 517 #define PG_ESC_SENSOR_CONFIG 517
#define PG_I2C_CONFIG 518 #define PG_I2C_CONFIG 518
#define PG_BETAFLIGHT_END 518 #define PG_DASHBOARD_CONFIG 519
#define PG_BETAFLIGHT_END 519
// OSD configuration (subject to change) // OSD configuration (subject to change)

View File

@ -19,14 +19,21 @@
#include "platform.h" #include "platform.h"
#include "drivers/bus_i2c.h"
#include "drivers/io_types.h" #include "drivers/io_types.h"
typedef union busDevice_u { typedef union busDevice_u {
struct deviceSpi_s { struct deviceSpi_s {
SPI_TypeDef *instance;
IO_t csnPin; IO_t csnPin;
} spi; } spi;
struct deviceI2C_s {
I2CDevice device;
uint8_t address;
} i2c;
} busDevice_t; } busDevice_t;
#ifdef TARGET_BUS_INIT #ifdef TARGET_BUS_INIT
void targetBusInit(void); void targetBusInit(void);
#endif #endif

View File

@ -45,6 +45,13 @@ typedef enum I2CDevice {
#define I2CDEV_COUNT 4 #define I2CDEV_COUNT 4
#endif #endif
// Macro to convert CLI bus number to I2CDevice.
#define I2C_CFG_TO_DEV(x) ((x) - 1)
// I2C device address range in 8-bit address mode
#define I2C_ADDR8_MIN 8
#define I2C_ADDR8_MAX 119
typedef struct i2cConfig_s { typedef struct i2cConfig_s {
ioTag_t ioTagScl[I2CDEV_COUNT]; ioTag_t ioTagScl[I2CDEV_COUNT];
ioTag_t ioTagSda[I2CDEV_COUNT]; ioTag_t ioTagSda[I2CDEV_COUNT];

View File

@ -20,6 +20,7 @@
struct displayPortVTable_s; struct displayPortVTable_s;
typedef struct displayPort_s { typedef struct displayPort_s {
const struct displayPortVTable_s *vTable; const struct displayPortVTable_s *vTable;
void *device;
uint8_t rows; uint8_t rows;
uint8_t cols; uint8_t cols;

View File

@ -176,78 +176,76 @@ static const uint8_t multiWiiFont[][5] = { // Refer to "Times New Roman" Font Da
{ 0x7A, 0x7E, 0x7E, 0x7E, 0x7A }, // (131) - 0x00C8 Vertical Bargraph - 6 (full) { 0x7A, 0x7E, 0x7E, 0x7E, 0x7A }, // (131) - 0x00C8 Vertical Bargraph - 6 (full)
}; };
#define OLED_address 0x3C // OLED at address 0x3C in 7bit static bool i2c_OLED_send_cmd(busDevice_t *bus, uint8_t command)
static bool i2c_OLED_send_cmd(uint8_t command)
{ {
return i2cWrite(OLED_I2C_INSTANCE, OLED_address, 0x80, command); return i2cWrite(bus->i2c.device, bus->i2c.address, 0x80, command);
} }
static bool i2c_OLED_send_byte(uint8_t val) static bool i2c_OLED_send_byte(busDevice_t *bus, uint8_t val)
{ {
return i2cWrite(OLED_I2C_INSTANCE, OLED_address, 0x40, val); return i2cWrite(bus->i2c.device, bus->i2c.address, 0x40, val);
} }
void i2c_OLED_clear_display(void) void i2c_OLED_clear_display(busDevice_t *bus)
{ {
i2c_OLED_send_cmd(0xa6); // Set Normal Display i2c_OLED_send_cmd(bus, 0xa6); // Set Normal Display
i2c_OLED_send_cmd(0xae); // Display OFF i2c_OLED_send_cmd(bus, 0xae); // Display OFF
i2c_OLED_send_cmd(0x20); // Set Memory Addressing Mode i2c_OLED_send_cmd(bus, 0x20); // Set Memory Addressing Mode
i2c_OLED_send_cmd(0x00); // Set Memory Addressing Mode to Horizontal addressing mode i2c_OLED_send_cmd(bus, 0x00); // Set Memory Addressing Mode to Horizontal addressing mode
i2c_OLED_send_cmd(0xb0); // set page address to 0 i2c_OLED_send_cmd(bus, 0xb0); // set page address to 0
i2c_OLED_send_cmd(0x40); // Display start line register to 0 i2c_OLED_send_cmd(bus, 0x40); // Display start line register to 0
i2c_OLED_send_cmd(0); // Set low col address to 0 i2c_OLED_send_cmd(bus, 0); // Set low col address to 0
i2c_OLED_send_cmd(0x10); // Set high col address to 0 i2c_OLED_send_cmd(bus, 0x10); // Set high col address to 0
for(uint16_t i = 0; i < 1024; i++) { // fill the display's RAM with graphic... 128*64 pixel picture for(uint16_t i = 0; i < 1024; i++) { // fill the display's RAM with graphic... 128*64 pixel picture
i2c_OLED_send_byte(0x00); // clear i2c_OLED_send_byte(bus, 0x00); // clear
} }
i2c_OLED_send_cmd(0x81); // Setup CONTRAST CONTROL, following byte is the contrast Value... always a 2 byte instruction i2c_OLED_send_cmd(bus, 0x81); // Setup CONTRAST CONTROL, following byte is the contrast Value... always a 2 byte instruction
i2c_OLED_send_cmd(200); // Here you can set the brightness 1 = dull, 255 is very bright i2c_OLED_send_cmd(bus, 200); // Here you can set the brightness 1 = dull, 255 is very bright
i2c_OLED_send_cmd(0xaf); // display on i2c_OLED_send_cmd(bus, 0xaf); // display on
} }
void i2c_OLED_clear_display_quick(void) void i2c_OLED_clear_display_quick(busDevice_t *bus)
{ {
i2c_OLED_send_cmd(0xb0); // set page address to 0 i2c_OLED_send_cmd(bus, 0xb0); // set page address to 0
i2c_OLED_send_cmd(0x40); // Display start line register to 0 i2c_OLED_send_cmd(bus, 0x40); // Display start line register to 0
i2c_OLED_send_cmd(0); // Set low col address to 0 i2c_OLED_send_cmd(bus, 0); // Set low col address to 0
i2c_OLED_send_cmd(0x10); // Set high col address to 0 i2c_OLED_send_cmd(bus, 0x10); // Set high col address to 0
for(uint16_t i = 0; i < 1024; i++) { // fill the display's RAM with graphic... 128*64 pixel picture for(uint16_t i = 0; i < 1024; i++) { // fill the display's RAM with graphic... 128*64 pixel picture
i2c_OLED_send_byte(0x00); // clear i2c_OLED_send_byte(bus, 0x00); // clear
} }
} }
void i2c_OLED_set_xy(uint8_t col, uint8_t row) void i2c_OLED_set_xy(busDevice_t *bus, uint8_t col, uint8_t row)
{ {
i2c_OLED_send_cmd(0xb0 + row); //set page address i2c_OLED_send_cmd(bus, 0xb0 + row); //set page address
i2c_OLED_send_cmd(0x00 + ((CHARACTER_WIDTH_TOTAL * col) & 0x0f)); //set low col address i2c_OLED_send_cmd(bus, 0x00 + ((CHARACTER_WIDTH_TOTAL * col) & 0x0f)); //set low col address
i2c_OLED_send_cmd(0x10 + (((CHARACTER_WIDTH_TOTAL * col) >> 4) & 0x0f)); //set high col address i2c_OLED_send_cmd(bus, 0x10 + (((CHARACTER_WIDTH_TOTAL * col) >> 4) & 0x0f)); //set high col address
} }
void i2c_OLED_set_line(uint8_t row) void i2c_OLED_set_line(busDevice_t *bus, uint8_t row)
{ {
i2c_OLED_send_cmd(0xb0 + row); //set page address i2c_OLED_send_cmd(bus, 0xb0 + row); //set page address
i2c_OLED_send_cmd(0); //set low col address i2c_OLED_send_cmd(bus, 0); //set low col address
i2c_OLED_send_cmd(0x10); //set high col address i2c_OLED_send_cmd(bus, 0x10); //set high col address
} }
void i2c_OLED_send_char(unsigned char ascii) void i2c_OLED_send_char(busDevice_t *bus, unsigned char ascii)
{ {
unsigned char i; unsigned char i;
uint8_t buffer; uint8_t buffer;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
buffer = multiWiiFont[ascii - 32][i]; buffer = multiWiiFont[ascii - 32][i];
buffer ^= CHAR_FORMAT; // apply buffer ^= CHAR_FORMAT; // apply
i2c_OLED_send_byte(buffer); i2c_OLED_send_byte(bus, buffer);
} }
i2c_OLED_send_byte(CHAR_FORMAT); // the gap i2c_OLED_send_byte(bus, CHAR_FORMAT); // the gap
} }
void i2c_OLED_send_string(const char *string) void i2c_OLED_send_string(busDevice_t *bus, const char *string)
{ {
// Sends a string of chars until null terminator // Sends a string of chars until null terminator
while (*string) { while (*string) {
i2c_OLED_send_char(*string); i2c_OLED_send_char(bus, *string);
string++; string++;
} }
} }
@ -255,38 +253,38 @@ void i2c_OLED_send_string(const char *string)
/** /**
* according to http://www.adafruit.com/datasheets/UG-2864HSWEG01.pdf Chapter 4.4 Page 15 * according to http://www.adafruit.com/datasheets/UG-2864HSWEG01.pdf Chapter 4.4 Page 15
*/ */
bool ug2864hsweg01InitI2C(void) bool ug2864hsweg01InitI2C(busDevice_t *bus)
{ {
// Set display OFF // Set display OFF
if (!i2c_OLED_send_cmd(0xAE)) { if (!i2c_OLED_send_cmd(bus, 0xAE)) {
return false; return false;
} }
i2c_OLED_send_cmd(0xD4); // Set Display Clock Divide Ratio / OSC Frequency i2c_OLED_send_cmd(bus, 0xD4); // Set Display Clock Divide Ratio / OSC Frequency
i2c_OLED_send_cmd(0x80); // Display Clock Divide Ratio / OSC Frequency i2c_OLED_send_cmd(bus, 0x80); // Display Clock Divide Ratio / OSC Frequency
i2c_OLED_send_cmd(0xA8); // Set Multiplex Ratio i2c_OLED_send_cmd(bus, 0xA8); // Set Multiplex Ratio
i2c_OLED_send_cmd(0x3F); // Multiplex Ratio for 128x64 (64-1) i2c_OLED_send_cmd(bus, 0x3F); // Multiplex Ratio for 128x64 (64-1)
i2c_OLED_send_cmd(0xD3); // Set Display Offset i2c_OLED_send_cmd(bus, 0xD3); // Set Display Offset
i2c_OLED_send_cmd(0x00); // Display Offset i2c_OLED_send_cmd(bus, 0x00); // Display Offset
i2c_OLED_send_cmd(0x40); // Set Display Start Line i2c_OLED_send_cmd(bus, 0x40); // Set Display Start Line
i2c_OLED_send_cmd(0x8D); // Set Charge Pump i2c_OLED_send_cmd(bus, 0x8D); // Set Charge Pump
i2c_OLED_send_cmd(0x14); // Charge Pump (0x10 External, 0x14 Internal DC/DC) i2c_OLED_send_cmd(bus, 0x14); // Charge Pump (0x10 External, 0x14 Internal DC/DC)
i2c_OLED_send_cmd(0xA1); // Set Segment Re-Map i2c_OLED_send_cmd(bus, 0xA1); // Set Segment Re-Map
i2c_OLED_send_cmd(0xC8); // Set Com Output Scan Direction i2c_OLED_send_cmd(bus, 0xC8); // Set Com Output Scan Direction
i2c_OLED_send_cmd(0xDA); // Set COM Hardware Configuration i2c_OLED_send_cmd(bus, 0xDA); // Set COM Hardware Configuration
i2c_OLED_send_cmd(0x12); // COM Hardware Configuration i2c_OLED_send_cmd(bus, 0x12); // COM Hardware Configuration
i2c_OLED_send_cmd(0x81); // Set Contrast i2c_OLED_send_cmd(bus, 0x81); // Set Contrast
i2c_OLED_send_cmd(0xCF); // Contrast i2c_OLED_send_cmd(bus, 0xCF); // Contrast
i2c_OLED_send_cmd(0xD9); // Set Pre-Charge Period i2c_OLED_send_cmd(bus, 0xD9); // Set Pre-Charge Period
i2c_OLED_send_cmd(0xF1); // Set Pre-Charge Period (0x22 External, 0xF1 Internal) i2c_OLED_send_cmd(bus, 0xF1); // Set Pre-Charge Period (0x22 External, 0xF1 Internal)
i2c_OLED_send_cmd(0xDB); // Set VCOMH Deselect Level i2c_OLED_send_cmd(bus, 0xDB); // Set VCOMH Deselect Level
i2c_OLED_send_cmd(0x40); // VCOMH Deselect Level i2c_OLED_send_cmd(bus, 0x40); // VCOMH Deselect Level
i2c_OLED_send_cmd(0xA4); // Set all pixels OFF i2c_OLED_send_cmd(bus, 0xA4); // Set all pixels OFF
i2c_OLED_send_cmd(0xA6); // Set display not inverted i2c_OLED_send_cmd(bus, 0xA6); // Set display not inverted
i2c_OLED_send_cmd(0xAF); // Set display On i2c_OLED_send_cmd(bus, 0xAF); // Set display On
i2c_OLED_clear_display(); i2c_OLED_clear_display(bus);
return true; return true;
} }

View File

@ -17,6 +17,8 @@
#pragma once #pragma once
#include "drivers/bus.h"
#define SCREEN_WIDTH 128 #define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64 #define SCREEN_HEIGHT 64
@ -34,12 +36,11 @@
#define VERTICAL_BARGRAPH_ZERO_CHARACTER (128 + 32) #define VERTICAL_BARGRAPH_ZERO_CHARACTER (128 + 32)
#define VERTICAL_BARGRAPH_CHARACTER_COUNT 7 #define VERTICAL_BARGRAPH_CHARACTER_COUNT 7
bool ug2864hsweg01InitI2C(void); bool ug2864hsweg01InitI2C(busDevice_t *bus);
void i2c_OLED_set_xy(uint8_t col, uint8_t row);
void i2c_OLED_set_line(uint8_t row);
void i2c_OLED_send_char(unsigned char ascii);
void i2c_OLED_send_string(const char *string);
void i2c_OLED_clear_display(void);
void i2c_OLED_clear_display_quick(void);
void i2c_OLED_set_xy(busDevice_t *bus, uint8_t col, uint8_t row);
void i2c_OLED_set_line(busDevice_t *bus, uint8_t row);
void i2c_OLED_send_char(busDevice_t *bus, unsigned char ascii);
void i2c_OLED_send_string(busDevice_t *bus, const char *string);
void i2c_OLED_clear_display(busDevice_t *bus);
void i2c_OLED_clear_display_quick(busDevice_t *bus);

View File

@ -53,6 +53,7 @@
#include "flight/pid.h" #include "flight/pid.h"
#include "flight/servos.h" #include "flight/servos.h"
#include "io/dashboard.h"
#include "io/gimbal.h" #include "io/gimbal.h"
#include "io/gps.h" #include "io/gps.h"
#include "io/ledstrip.h" #include "io/ledstrip.h"
@ -720,6 +721,10 @@ const clivalue_t valueTable[] = {
{ "esc_sensor_halfduplex", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_ESC_SENSOR_CONFIG, offsetof(escSensorConfig_t, halfDuplex) }, { "esc_sensor_halfduplex", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_ESC_SENSOR_CONFIG, offsetof(escSensorConfig_t, halfDuplex) },
#endif #endif
{ "led_inversion", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, ((1 << STATUS_LED_NUMBER) - 1) }, PG_STATUS_LED_CONFIG, offsetof(statusLedConfig_t, inversion) }, { "led_inversion", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, ((1 << STATUS_LED_NUMBER) - 1) }, PG_STATUS_LED_CONFIG, offsetof(statusLedConfig_t, inversion) },
#ifdef USE_DASHBOARD
{ "dashboard_i2c_bus", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, I2CDEV_COUNT }, PG_DASHBOARD_CONFIG, offsetof(dashboardConfig_t, device) },
{ "dashboard_i2c_addr", VAR_UINT8 | MASTER_VALUE, .config.minmax = { I2C_ADDR8_MIN, I2C_ADDR8_MAX }, PG_DASHBOARD_CONFIG, offsetof(dashboardConfig_t, address) },
#endif
}; };
const uint16_t valueTableEntryCount = ARRAYLEN(valueTable); const uint16_t valueTableEntryCount = ARRAYLEN(valueTable);

View File

@ -31,6 +31,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "drivers/bus.h"
#include "drivers/display.h" #include "drivers/display.h"
#include "drivers/display_ug2864hsweg01.h" #include "drivers/display_ug2864hsweg01.h"
#include "drivers/time.h" #include "drivers/time.h"
@ -71,11 +72,20 @@
#include "sensors/sensors.h" #include "sensors/sensors.h"
PG_REGISTER_WITH_RESET_TEMPLATE(dashboardConfig_t, dashboardConfig, PG_DASHBOARD_CONFIG, 0);
PG_RESET_TEMPLATE(dashboardConfig_t, dashboardConfig,
.device = DASHBOARD_I2C_INSTANCE,
.address = DASHBOARD_I2C_ADDRESS,
);
#define MICROSECONDS_IN_A_SECOND (1000 * 1000) #define MICROSECONDS_IN_A_SECOND (1000 * 1000)
#define DISPLAY_UPDATE_FREQUENCY (MICROSECONDS_IN_A_SECOND / 5) #define DISPLAY_UPDATE_FREQUENCY (MICROSECONDS_IN_A_SECOND / 5)
#define PAGE_CYCLE_FREQUENCY (MICROSECONDS_IN_A_SECOND * 5) #define PAGE_CYCLE_FREQUENCY (MICROSECONDS_IN_A_SECOND * 5)
static busDevice_t bus;
static uint32_t nextDisplayUpdateAt = 0; static uint32_t nextDisplayUpdateAt = 0;
static bool dashboardPresent = false; static bool dashboardPresent = false;
@ -119,12 +129,14 @@ typedef struct pageState_s {
static pageState_t pageState; static pageState_t pageState;
void resetDisplay(void) { void resetDisplay(void)
dashboardPresent = ug2864hsweg01InitI2C(); {
dashboardPresent = ug2864hsweg01InitI2C(&bus);
} }
void LCDprint(uint8_t i) { void LCDprint(uint8_t i)
i2c_OLED_send_char(i); {
i2c_OLED_send_char(&bus, i);
} }
void padLineBuffer(void) void padLineBuffer(void)
@ -170,8 +182,8 @@ void fillScreenWithCharacters()
{ {
for (uint8_t row = 0; row < SCREEN_CHARACTER_ROW_COUNT; row++) { for (uint8_t row = 0; row < SCREEN_CHARACTER_ROW_COUNT; row++) {
for (uint8_t column = 0; column < SCREEN_CHARACTER_COLUMN_COUNT; column++) { for (uint8_t column = 0; column < SCREEN_CHARACTER_COLUMN_COUNT; column++) {
i2c_OLED_set_xy(column, row); i2c_OLED_set_xy(&bus, column, row);
i2c_OLED_send_char('A' + column); i2c_OLED_send_char(&bus, 'A' + column);
} }
} }
} }
@ -181,22 +193,22 @@ void fillScreenWithCharacters()
void updateTicker(void) void updateTicker(void)
{ {
static uint8_t tickerIndex = 0; static uint8_t tickerIndex = 0;
i2c_OLED_set_xy(SCREEN_CHARACTER_COLUMN_COUNT - 1, 0); i2c_OLED_set_xy(&bus, SCREEN_CHARACTER_COLUMN_COUNT - 1, 0);
i2c_OLED_send_char(tickerCharacters[tickerIndex]); i2c_OLED_send_char(&bus, tickerCharacters[tickerIndex]);
tickerIndex++; tickerIndex++;
tickerIndex = tickerIndex % TICKER_CHARACTER_COUNT; tickerIndex = tickerIndex % TICKER_CHARACTER_COUNT;
} }
void updateRxStatus(void) void updateRxStatus(void)
{ {
i2c_OLED_set_xy(SCREEN_CHARACTER_COLUMN_COUNT - 2, 0); i2c_OLED_set_xy(&bus, SCREEN_CHARACTER_COLUMN_COUNT - 2, 0);
char rxStatus = '!'; char rxStatus = '!';
if (rxIsReceivingSignal()) { if (rxIsReceivingSignal()) {
rxStatus = 'r'; rxStatus = 'r';
} if (rxAreFlightChannelsValid()) { } if (rxAreFlightChannelsValid()) {
rxStatus = 'R'; rxStatus = 'R';
} }
i2c_OLED_send_char(rxStatus); i2c_OLED_send_char(&bus, rxStatus);
} }
void updateFailsafeStatus(void) void updateFailsafeStatus(void)
@ -222,19 +234,19 @@ void updateFailsafeStatus(void)
failsafeIndicator = 'r'; failsafeIndicator = 'r';
break; break;
} }
i2c_OLED_set_xy(SCREEN_CHARACTER_COLUMN_COUNT - 3, 0); i2c_OLED_set_xy(&bus, SCREEN_CHARACTER_COLUMN_COUNT - 3, 0);
i2c_OLED_send_char(failsafeIndicator); i2c_OLED_send_char(&bus, failsafeIndicator);
} }
void showTitle() void showTitle()
{ {
i2c_OLED_set_line(0); i2c_OLED_set_line(&bus, 0);
i2c_OLED_send_string(pageState.page->title); i2c_OLED_send_string(&bus, pageState.page->title);
} }
void handlePageChange(void) void handlePageChange(void)
{ {
i2c_OLED_clear_display_quick(); i2c_OLED_clear_display_quick(&bus);
showTitle(); showTitle();
} }
@ -253,7 +265,7 @@ void showRxPage(void)
{ {
for (uint8_t channelIndex = 0; channelIndex < rxRuntimeConfig.channelCount && channelIndex < RX_CHANNELS_PER_PAGE_COUNT; channelIndex += 2) { for (uint8_t channelIndex = 0; channelIndex < rxRuntimeConfig.channelCount && channelIndex < RX_CHANNELS_PER_PAGE_COUNT; channelIndex += 2) {
i2c_OLED_set_line((channelIndex / 2) + PAGE_TITLE_LINE_COUNT); i2c_OLED_set_line(&bus, (channelIndex / 2) + PAGE_TITLE_LINE_COUNT);
drawRxChannel(channelIndex, HALF_SCREEN_CHARACTER_COLUMN_COUNT); drawRxChannel(channelIndex, HALF_SCREEN_CHARACTER_COLUMN_COUNT);
@ -274,11 +286,11 @@ void showWelcomePage(void)
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT; uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
tfp_sprintf(lineBuffer, "v%s (%s)", FC_VERSION_STRING, shortGitRevision); tfp_sprintf(lineBuffer, "v%s (%s)", FC_VERSION_STRING, shortGitRevision);
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(targetName); i2c_OLED_send_string(&bus, targetName);
} }
void showArmedPage(void) void showArmedPage(void)
@ -290,8 +302,8 @@ void showProfilePage(void)
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT; uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
tfp_sprintf(lineBuffer, "Profile: %d", getCurrentPidProfileIndex()); tfp_sprintf(lineBuffer, "Profile: %d", getCurrentPidProfileIndex());
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
static const char* const axisTitles[3] = {"ROL", "PIT", "YAW"}; static const char* const axisTitles[3] = {"ROL", "PIT", "YAW"};
const pidProfile_t *pidProfile = currentPidProfile; const pidProfile_t *pidProfile = currentPidProfile;
@ -303,14 +315,14 @@ void showProfilePage(void)
pidProfile->pid[axis].D pidProfile->pid[axis].D
); );
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
const uint8_t currentRateProfileIndex = getCurrentControlRateProfileIndex(); const uint8_t currentRateProfileIndex = getCurrentControlRateProfileIndex();
tfp_sprintf(lineBuffer, "Rate profile: %d", currentRateProfileIndex); tfp_sprintf(lineBuffer, "Rate profile: %d", currentRateProfileIndex);
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
const controlRateConfig_t *controlRateConfig = controlRateProfiles(currentRateProfileIndex); const controlRateConfig_t *controlRateConfig = controlRateProfiles(currentRateProfileIndex);
tfp_sprintf(lineBuffer, "RCE: %d, RCR: %d", tfp_sprintf(lineBuffer, "RCE: %d, RCR: %d",
@ -318,8 +330,8 @@ void showProfilePage(void)
controlRateConfig->rcRate8 controlRateConfig->rcRate8
); );
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "RR:%d PR:%d YR:%d", tfp_sprintf(lineBuffer, "RR:%d PR:%d YR:%d",
controlRateConfig->rates[FD_ROLL], controlRateConfig->rates[FD_ROLL],
@ -327,8 +339,8 @@ void showProfilePage(void)
controlRateConfig->rates[FD_YAW] controlRateConfig->rates[FD_YAW]
); );
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
#define SATELLITE_COUNT (sizeof(GPS_svinfo_cno) / sizeof(GPS_svinfo_cno[0])) #define SATELLITE_COUNT (sizeof(GPS_svinfo_cno) / sizeof(GPS_svinfo_cno[0]))
#define SATELLITE_GRAPH_LEFT_OFFSET ((SCREEN_CHARACTER_COLUMN_COUNT - SATELLITE_COUNT) / 2) #define SATELLITE_GRAPH_LEFT_OFFSET ((SCREEN_CHARACTER_COLUMN_COUNT - SATELLITE_COUNT) / 2)
@ -351,77 +363,77 @@ void showGpsPage() {
gpsTicker = gpsTicker % TICKER_CHARACTER_COUNT; gpsTicker = gpsTicker % TICKER_CHARACTER_COUNT;
} }
i2c_OLED_set_xy(0, rowIndex); i2c_OLED_set_xy(&bus, 0, rowIndex);
i2c_OLED_send_char(tickerCharacters[gpsTicker]); i2c_OLED_send_char(&bus, tickerCharacters[gpsTicker]);
i2c_OLED_set_xy(MAX(0, SATELLITE_GRAPH_LEFT_OFFSET), rowIndex++); i2c_OLED_set_xy(&bus, MAX(0, SATELLITE_GRAPH_LEFT_OFFSET), rowIndex++);
uint32_t index; uint32_t index;
for (index = 0; index < SATELLITE_COUNT && index < SCREEN_CHARACTER_COLUMN_COUNT; index++) { for (index = 0; index < SATELLITE_COUNT && index < SCREEN_CHARACTER_COLUMN_COUNT; index++) {
uint8_t bargraphOffset = ((uint16_t) GPS_svinfo_cno[index] * VERTICAL_BARGRAPH_CHARACTER_COUNT) / (GPS_DBHZ_MAX - 1); uint8_t bargraphOffset = ((uint16_t) GPS_svinfo_cno[index] * VERTICAL_BARGRAPH_CHARACTER_COUNT) / (GPS_DBHZ_MAX - 1);
bargraphOffset = MIN(bargraphOffset, VERTICAL_BARGRAPH_CHARACTER_COUNT - 1); bargraphOffset = MIN(bargraphOffset, VERTICAL_BARGRAPH_CHARACTER_COUNT - 1);
i2c_OLED_send_char(VERTICAL_BARGRAPH_ZERO_CHARACTER + bargraphOffset); i2c_OLED_send_char(&bus, VERTICAL_BARGRAPH_ZERO_CHARACTER + bargraphOffset);
} }
char fixChar = STATE(GPS_FIX) ? 'Y' : 'N'; char fixChar = STATE(GPS_FIX) ? 'Y' : 'N';
tfp_sprintf(lineBuffer, "Sats: %d Fix: %c", gpsSol.numSat, fixChar); tfp_sprintf(lineBuffer, "Sats: %d Fix: %c", gpsSol.numSat, fixChar);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "La/Lo: %d/%d", gpsSol.llh.lat / GPS_DEGREES_DIVIDER, gpsSol.llh.lon / GPS_DEGREES_DIVIDER); tfp_sprintf(lineBuffer, "La/Lo: %d/%d", gpsSol.llh.lat / GPS_DEGREES_DIVIDER, gpsSol.llh.lon / GPS_DEGREES_DIVIDER);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "Spd: %d", gpsSol.groundSpeed); tfp_sprintf(lineBuffer, "Spd: %d", gpsSol.groundSpeed);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_line(rowIndex); i2c_OLED_set_line(&bus, rowIndex);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "GC: %d", gpsSol.groundCourse); tfp_sprintf(lineBuffer, "GC: %d", gpsSol.groundCourse);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_xy(HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++); i2c_OLED_set_xy(&bus, HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "RX: %d", GPS_packetCount); tfp_sprintf(lineBuffer, "RX: %d", GPS_packetCount);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_line(rowIndex); i2c_OLED_set_line(&bus, rowIndex);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "ERRs: %d", gpsData.errors, gpsData.timeouts); tfp_sprintf(lineBuffer, "ERRs: %d", gpsData.errors, gpsData.timeouts);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_xy(HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++); i2c_OLED_set_xy(&bus, HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "Dt: %d", gpsData.lastMessage - gpsData.lastLastMessage); tfp_sprintf(lineBuffer, "Dt: %d", gpsData.lastMessage - gpsData.lastLastMessage);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_line(rowIndex); i2c_OLED_set_line(&bus, rowIndex);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
tfp_sprintf(lineBuffer, "TOs: %d", gpsData.timeouts); tfp_sprintf(lineBuffer, "TOs: %d", gpsData.timeouts);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_xy(HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++); i2c_OLED_set_xy(&bus, HALF_SCREEN_CHARACTER_COLUMN_COUNT, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
strncpy(lineBuffer, gpsPacketLog, GPS_PACKET_LOG_ENTRY_COUNT); strncpy(lineBuffer, gpsPacketLog, GPS_PACKET_LOG_ENTRY_COUNT);
padHalfLineBuffer(); padHalfLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
#ifdef GPS_PH_DEBUG #ifdef GPS_PH_DEBUG
tfp_sprintf(lineBuffer, "Angles: P:%d R:%d", GPS_angle[PITCH], GPS_angle[ROLL]); tfp_sprintf(lineBuffer, "Angles: P:%d R:%d", GPS_angle[PITCH], GPS_angle[ROLL]);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
#endif #endif
#if 0 #if 0
tfp_sprintf(lineBuffer, "%d %d %d %d", debug[0], debug[1], debug[2], debug[3]); tfp_sprintf(lineBuffer, "%d %d %d %d", debug[0], debug[1], debug[2], debug[3]);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
#endif #endif
} }
#endif #endif
@ -433,11 +445,11 @@ void showBatteryPage(void)
if (batteryConfig()->voltageMeterSource != VOLTAGE_METER_NONE) { if (batteryConfig()->voltageMeterSource != VOLTAGE_METER_NONE) {
tfp_sprintf(lineBuffer, "Volts: %d.%1d Cells: %d", getBatteryVoltage() / 10, getBatteryVoltage() % 10, getBatteryCellCount()); tfp_sprintf(lineBuffer, "Volts: %d.%1d Cells: %d", getBatteryVoltage() / 10, getBatteryVoltage() % 10, getBatteryCellCount());
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
uint8_t batteryPercentage = calculateBatteryPercentageRemaining(); uint8_t batteryPercentage = calculateBatteryPercentageRemaining();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, batteryPercentage); drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, batteryPercentage);
} }
@ -446,11 +458,11 @@ void showBatteryPage(void)
int32_t amperage = getAmperage(); int32_t amperage = getAmperage();
tfp_sprintf(lineBuffer, "Amps: %d.%2d mAh: %d", amperage / 100, amperage % 100, getMAhDrawn()); tfp_sprintf(lineBuffer, "Amps: %d.%2d mAh: %d", amperage / 100, amperage % 100, getMAhDrawn());
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
uint8_t capacityPercentage = calculateBatteryPercentageRemaining(); uint8_t capacityPercentage = calculateBatteryPercentageRemaining();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, capacityPercentage); drawHorizonalPercentageBar(SCREEN_CHARACTER_COLUMN_COUNT, capacityPercentage);
} }
} }
@ -460,36 +472,36 @@ void showSensorsPage(void)
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT; uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
static const char *format = "%s %5d %5d %5d"; static const char *format = "%s %5d %5d %5d";
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(" X Y Z"); i2c_OLED_send_string(&bus, " X Y Z");
if (sensors(SENSOR_ACC)) { if (sensors(SENSOR_ACC)) {
tfp_sprintf(lineBuffer, format, "ACC", acc.accSmooth[X], acc.accSmooth[Y], acc.accSmooth[Z]); tfp_sprintf(lineBuffer, format, "ACC", acc.accSmooth[X], acc.accSmooth[Y], acc.accSmooth[Z]);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
if (sensors(SENSOR_GYRO)) { if (sensors(SENSOR_GYRO)) {
tfp_sprintf(lineBuffer, format, "GYR", lrintf(gyro.gyroADCf[X]), lrintf(gyro.gyroADCf[Y]), lrintf(gyro.gyroADCf[Z])); tfp_sprintf(lineBuffer, format, "GYR", lrintf(gyro.gyroADCf[X]), lrintf(gyro.gyroADCf[Y]), lrintf(gyro.gyroADCf[Z]));
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
#ifdef MAG #ifdef MAG
if (sensors(SENSOR_MAG)) { if (sensors(SENSOR_MAG)) {
tfp_sprintf(lineBuffer, format, "MAG", mag.magADC[X], mag.magADC[Y], mag.magADC[Z]); tfp_sprintf(lineBuffer, format, "MAG", mag.magADC[X], mag.magADC[Y], mag.magADC[Z]);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
#endif #endif
tfp_sprintf(lineBuffer, format, "I&H", attitude.values.roll, attitude.values.pitch, DECIDEGREES_TO_DEGREES(attitude.values.yaw)); tfp_sprintf(lineBuffer, format, "I&H", attitude.values.roll, attitude.values.pitch, DECIDEGREES_TO_DEGREES(attitude.values.yaw));
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
/* /*
uint8_t length; uint8_t length;
@ -502,8 +514,8 @@ void showSensorsPage(void)
} }
ftoa(EstG.A[Y], lineBuffer + length); ftoa(EstG.A[Y], lineBuffer + length);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
ftoa(EstG.A[Z], lineBuffer); ftoa(EstG.A[Z], lineBuffer);
length = strlen(lineBuffer); length = strlen(lineBuffer);
@ -513,8 +525,8 @@ void showSensorsPage(void)
} }
ftoa(smallAngle, lineBuffer + length); ftoa(smallAngle, lineBuffer + length);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
*/ */
} }
@ -525,8 +537,8 @@ void showTasksPage(void)
uint8_t rowIndex = PAGE_TITLE_LINE_COUNT; uint8_t rowIndex = PAGE_TITLE_LINE_COUNT;
static const char *format = "%2d%6d%5d%4d%4d"; static const char *format = "%2d%6d%5d%4d%4d";
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string("Task max avg mx% av%"); i2c_OLED_send_string(&bus, "Task max avg mx% av%");
cfTaskInfo_t taskInfo; cfTaskInfo_t taskInfo;
for (cfTaskId_e taskId = 0; taskId < TASK_COUNT; ++taskId) { for (cfTaskId_e taskId = 0; taskId < TASK_COUNT; ++taskId) {
getTaskInfo(taskId, &taskInfo); getTaskInfo(taskId, &taskInfo);
@ -536,8 +548,8 @@ void showTasksPage(void)
const int averageLoad = (taskInfo.averageExecutionTime * taskFrequency + 5000) / 10000; const int averageLoad = (taskInfo.averageExecutionTime * taskFrequency + 5000) / 10000;
tfp_sprintf(lineBuffer, format, taskId, taskInfo.maxExecutionTime, taskInfo.averageExecutionTime, maxLoad, averageLoad); tfp_sprintf(lineBuffer, format, taskId, taskInfo.maxExecutionTime, taskInfo.averageExecutionTime, maxLoad, averageLoad);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(&bus, rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
if (rowIndex > SCREEN_CHARACTER_ROW_COUNT) { if (rowIndex > SCREEN_CHARACTER_ROW_COUNT) {
break; break;
} }
@ -553,8 +565,8 @@ void showDebugPage(void)
for (int rowIndex = 0; rowIndex < 4; rowIndex++) { for (int rowIndex = 0; rowIndex < 4; rowIndex++) {
tfp_sprintf(lineBuffer, "%d = %5d", rowIndex, debug[rowIndex]); tfp_sprintf(lineBuffer, "%d = %5d", rowIndex, debug[rowIndex]);
padLineBuffer(); padLineBuffer();
i2c_OLED_set_line(rowIndex + PAGE_TITLE_LINE_COUNT); i2c_OLED_set_line(&bus, rowIndex + PAGE_TITLE_LINE_COUNT);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(&bus, lineBuffer);
} }
} }
#endif #endif
@ -664,11 +676,14 @@ void dashboardUpdate(timeUs_t currentTimeUs)
void dashboardInit(void) void dashboardInit(void)
{ {
bus.i2c.device = I2C_CFG_TO_DEV(dashboardConfig()->device);
bus.i2c.address = dashboardConfig()->address;
delay(200); delay(200);
resetDisplay(); resetDisplay();
delay(200); delay(200);
displayPort = displayPortOledInit(); displayPort = displayPortOledInit(&bus);
#if defined(CMS) #if defined(CMS)
if (dashboardPresent) { if (dashboardPresent) {
cmsDisplayPortRegister(displayPort); cmsDisplayPortRegister(displayPort);

View File

@ -16,9 +16,26 @@
*/ */
#include "common/time.h" #include "common/time.h"
#include "config/parameter_group.h"
#include "drivers/bus_i2c.h"
#define ENABLE_DEBUG_DASHBOARD_PAGE #define ENABLE_DEBUG_DASHBOARD_PAGE
#ifdef OLED_I2C_INSTANCE
#define DASHBOARD_I2C_INSTANCE OLED_I2C_INSTANCE
#else
#define DASHBOARD_I2C_INSTANCE I2CDEV_1
#endif
#define DASHBOARD_I2C_ADDRESS 0x3C // OLED at address 0x3C in 7bit
typedef struct dashboardConfig_s {
I2CDevice device;
uint8_t address;
} dashboardConfig_t;
PG_DECLARE(dashboardConfig_t, dashboardConfig);
typedef enum { typedef enum {
PAGE_WELCOME, PAGE_WELCOME,
PAGE_ARMED, PAGE_ARMED,

View File

@ -41,8 +41,7 @@ static int oledRelease(displayPort_t *displayPort)
static int oledClearScreen(displayPort_t *displayPort) static int oledClearScreen(displayPort_t *displayPort)
{ {
UNUSED(displayPort); i2c_OLED_clear_display_quick(displayPort->device);
i2c_OLED_clear_display_quick();
return 0; return 0;
} }
@ -59,17 +58,15 @@ static int oledScreenSize(const displayPort_t *displayPort)
static int oledWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) static int oledWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s)
{ {
UNUSED(displayPort); i2c_OLED_set_xy(displayPort->device, x, y);
i2c_OLED_set_xy(x, y); i2c_OLED_send_string(displayPort->device, s);
i2c_OLED_send_string(s);
return 0; return 0;
} }
static int oledWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) static int oledWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c)
{ {
UNUSED(displayPort); i2c_OLED_set_xy(displayPort->device, x, y);
i2c_OLED_set_xy(x, y); i2c_OLED_send_char(displayPort->device, c);
i2c_OLED_send_char(c);
return 0; return 0;
} }
@ -110,8 +107,9 @@ static const displayPortVTable_t oledVTable = {
.txBytesFree = oledTxBytesFree .txBytesFree = oledTxBytesFree
}; };
displayPort_t *displayPortOledInit(void) displayPort_t *displayPortOledInit(void *device)
{ {
oledDisplayPort.device = device;
displayInit(&oledDisplayPort, &oledVTable); displayInit(&oledDisplayPort, &oledVTable);
oledDisplayPort.rows = SCREEN_CHARACTER_ROW_COUNT; oledDisplayPort.rows = SCREEN_CHARACTER_ROW_COUNT;
oledDisplayPort.cols = SCREEN_CHARACTER_COLUMN_COUNT; oledDisplayPort.cols = SCREEN_CHARACTER_COLUMN_COUNT;

View File

@ -17,4 +17,4 @@
#pragma once #pragma once
displayPort_t *displayPortOledInit(void); displayPort_t *displayPortOledInit(void *device);