OLED Display - Add two pages: RX info and Welcome.

The RX info page shows channel letters and bar graphs for the first 8
channels.
The Welcome page shows the target and cleanflight git revision.
This commit is contained in:
Dominic Clifton 2014-09-21 05:09:01 +01:00
parent 94c1023493
commit c898ca4634
7 changed files with 155 additions and 25 deletions

View File

@ -146,6 +146,7 @@ INCLUDE_DIRS := $(INCLUDE_DIRS) \
VPATH := $(VPATH):$(TARGET_DIR) VPATH := $(VPATH):$(TARGET_DIR)
COMMON_SRC = build_config.c \ COMMON_SRC = build_config.c \
version.c \
$(TARGET_SRC) \ $(TARGET_SRC) \
config/config.c \ config/config.c \
config/runtime_config.c \ config/runtime_config.c \

View File

@ -21,11 +21,13 @@
#include <string.h> #include <string.h>
#include "platform.h" #include "platform.h"
#include "version.h"
#include "build_config.h" #include "build_config.h"
#include "drivers/serial.h" #include "drivers/serial.h"
#include "common/printf.h" #include "common/printf.h"
#include "common/maths.h"
#ifdef DISPLAY #ifdef DISPLAY
@ -39,6 +41,8 @@
#include "sensors/sensors.h" #include "sensors/sensors.h"
#include "sensors/compass.h" #include "sensors/compass.h"
#include "rx/rx.h"
#include "config/runtime_config.h" #include "config/runtime_config.h"
#include "display.h" #include "display.h"
@ -48,28 +52,34 @@
#define DISPLAY_UPDATE_FREQUENCY (MILLISECONDS_IN_A_SECOND / 10) #define DISPLAY_UPDATE_FREQUENCY (MILLISECONDS_IN_A_SECOND / 10)
#define PAGE_CYCLE_FREQUENCY (MILLISECONDS_IN_A_SECOND * 5) #define PAGE_CYCLE_FREQUENCY (MILLISECONDS_IN_A_SECOND * 5)
uint32_t nextDisplayUpdateAt = 0; static uint32_t nextDisplayUpdateAt = 0;
uint32_t nextPageAt = 0;
char lineBuffer[SCREEN_CHARACTER_COLUMN_COUNT]; static rxConfig_t *rxConfig;
static char lineBuffer[SCREEN_CHARACTER_COLUMN_COUNT];
typedef enum { typedef enum {
PAGE_WELCOME,
PAGE_ARMED, PAGE_ARMED,
PAGE_BATTERY, PAGE_BATTERY,
PAGE_SENSORS PAGE_SENSORS,
PAGE_RX,
} pageId_e; } pageId_e;
const char* pageTitles[] = { const char* pageTitles[] = {
"CLEANFLIGHT",
"ARMED", "ARMED",
"BATTERY", "BATTERY",
"SENSORS" "SENSORS",
"RX"
}; };
#define PAGE_COUNT (PAGE_SENSORS + 1) #define PAGE_COUNT (PAGE_RX + 1)
const uint8_t cyclePageIds[] = { const uint8_t cyclePageIds[] = {
PAGE_BATTERY, PAGE_BATTERY,
PAGE_SENSORS PAGE_SENSORS,
PAGE_RX
}; };
#define CYCLE_PAGE_ID_COUNT (sizeof(cyclePageIds) / sizeof(cyclePageIds[0])) #define CYCLE_PAGE_ID_COUNT (sizeof(cyclePageIds) / sizeof(cyclePageIds[0]))
@ -77,10 +87,19 @@ const uint8_t cyclePageIds[] = {
static const char* tickerCharacters = "|/-\\"; static const char* tickerCharacters = "|/-\\";
#define TICKER_CHARACTER_COUNT (sizeof(tickerCharacters) / sizeof(char)) #define TICKER_CHARACTER_COUNT (sizeof(tickerCharacters) / sizeof(char))
typedef enum {
PAGE_STATE_FLAG_NONE = 0,
PAGE_STATE_FLAG_CYCLE_ENABLED = (1 << 0),
PAGE_STATE_FLAG_FORCE_PAGE_CHANGE = (1 << 1)
} pageFlags_e;
typedef struct pageState_s { typedef struct pageState_s {
bool pageChanging; bool pageChanging;
pageId_e pageId; pageId_e pageId;
pageId_e pageIdBeforeArming;
uint8_t pageFlags;
uint8_t cycleIndex; uint8_t cycleIndex;
uint32_t nextPageAt;
} pageState_t; } pageState_t;
static pageState_t pageState; static pageState_t pageState;
@ -89,6 +108,14 @@ void LCDprint(uint8_t i) {
i2c_OLED_send_char(i); i2c_OLED_send_char(i);
} }
void padLineBuffer(void)
{
uint8_t length = strlen(lineBuffer);
while (length < sizeof(lineBuffer) - 1) {
lineBuffer[length++] = ' ';
}
}
// LCDbar(n,v) : draw a bar graph - n number of chars for width, v value in % to display // LCDbar(n,v) : draw a bar graph - n number of chars for width, v value in % to display
void drawHorizonalPercentageBar(uint8_t width,uint8_t percent) { void drawHorizonalPercentageBar(uint8_t width,uint8_t percent) {
uint8_t i, j; uint8_t i, j;
@ -141,15 +168,55 @@ void handlePageChange(void)
showTitle(); showTitle();
} }
void drawRxChannel(uint8_t channelIndex, uint8_t width)
{
uint32_t percentage;
LCDprint(rcChannelLetters[channelIndex]);
percentage = (constrain(rcData[channelIndex], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN);
drawHorizonalPercentageBar(width - 1, percentage);
}
void showRxPage(void)
{
for (uint8_t channelIndex = 0; channelIndex < 8; channelIndex += 2) {
i2c_OLED_set_line((channelIndex / 2) + 1);
uint8_t width = SCREEN_CHARACTER_COLUMN_COUNT / 2;
drawRxChannel(channelIndex, width);
if (width * 2 != SCREEN_CHARACTER_COLUMN_COUNT) {
LCDprint(' ');
}
drawRxChannel(channelIndex + 1, width);
}
}
void showWelcomePage(void)
{
tfp_sprintf(lineBuffer, "Rev: %s", shortGitRevision);
i2c_OLED_set_line(1);
i2c_OLED_send_string(lineBuffer);
tfp_sprintf(lineBuffer, "Target: %s", targetName);
i2c_OLED_set_line(2);
i2c_OLED_send_string(lineBuffer);
}
void showArmedPage(void) void showArmedPage(void)
{ {
} }
void showBatteryPage(void) void showBatteryPage(void)
{ {
tfp_sprintf(lineBuffer, "volts: %d.%d, cells: %d", vbat / 10, vbat % 10, batteryCellCount); tfp_sprintf(lineBuffer, "Volts: %d.%d, Cells: %d", vbat / 10, vbat % 10, batteryCellCount);
i2c_OLED_set_line(1); i2c_OLED_set_line(1);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(lineBuffer);
padLineBuffer();
uint32_t batteryPercentage = calculateBatteryPercentage(); uint32_t batteryPercentage = calculateBatteryPercentage();
i2c_OLED_set_line(2); i2c_OLED_set_line(2);
@ -163,18 +230,21 @@ void showSensorsPage(void)
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(" X Y Z"); i2c_OLED_send_string(" X Y Z");
if (sensors(SENSOR_ACC)) { if (sensors(SENSOR_ACC)) {
tfp_sprintf(lineBuffer, "Acc : %4d %4d %4d", accSmooth[X], accSmooth[Y], accSmooth[Z]); tfp_sprintf(lineBuffer, "A = %5d %5d %5d", accSmooth[X], accSmooth[Y], accSmooth[Z]);
padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(lineBuffer);
} }
if (sensors(SENSOR_GYRO)) { if (sensors(SENSOR_GYRO)) {
tfp_sprintf(lineBuffer, "Gryo: %4d %4d %4d", gyroADC[X], gyroADC[Y], gyroADC[Z]); tfp_sprintf(lineBuffer, "G = %5d %5d %5d", gyroADC[X], gyroADC[Y], gyroADC[Z]);
padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(lineBuffer);
} }
#ifdef MAG #ifdef MAG
if (sensors(SENSOR_MAG)) { if (sensors(SENSOR_MAG)) {
tfp_sprintf(lineBuffer, "Comp: %4d %4d %4d", magADC[X], magADC[Y], magADC[Z]); tfp_sprintf(lineBuffer, "M = %5d %5d %5d", magADC[X], magADC[Y], magADC[Z]);
padLineBuffer();
i2c_OLED_set_line(rowIndex++); i2c_OLED_set_line(rowIndex++);
i2c_OLED_send_string(lineBuffer); i2c_OLED_send_string(lineBuffer);
} }
@ -201,36 +271,44 @@ void updateDisplay(void)
if (!armedStateChanged) { if (!armedStateChanged) {
return; return;
} }
pageState.pageIdBeforeArming = pageState.pageId;
pageState.pageId = PAGE_ARMED; pageState.pageId = PAGE_ARMED;
pageState.pageChanging = true; pageState.pageChanging = true;
} else { } else {
if (armedStateChanged) { if (armedStateChanged) {
nextPageAt = now; pageState.pageFlags |= PAGE_STATE_FLAG_FORCE_PAGE_CHANGE;
pageState.cycleIndex = CYCLE_PAGE_ID_COUNT; pageState.pageId = pageState.pageIdBeforeArming;
} }
pageState.pageChanging = (int32_t)(now - nextPageAt) >= 0L;
if (pageState.pageChanging) { pageState.pageChanging = (pageState.pageFlags & PAGE_STATE_FLAG_FORCE_PAGE_CHANGE) || ((int32_t)(now - pageState.nextPageAt) >= 0L);
nextPageAt = now + PAGE_CYCLE_FREQUENCY; if (pageState.pageChanging && (pageState.pageFlags & PAGE_STATE_FLAG_CYCLE_ENABLED)) {
pageState.nextPageAt = now + PAGE_CYCLE_FREQUENCY;
pageState.cycleIndex++; pageState.cycleIndex++;
pageState.cycleIndex = pageState.cycleIndex % CYCLE_PAGE_ID_COUNT; pageState.cycleIndex = pageState.cycleIndex % CYCLE_PAGE_ID_COUNT;
pageState.pageId = cyclePageIds[pageState.cycleIndex]; pageState.pageId = cyclePageIds[pageState.cycleIndex];
} }
} }
if (pageState.pageChanging) { if (pageState.pageChanging) {
handlePageChange(); handlePageChange();
pageState.pageFlags &= ~PAGE_STATE_FLAG_FORCE_PAGE_CHANGE;
} }
switch(pageState.pageId) { switch(pageState.pageId) {
case PAGE_WELCOME:
showWelcomePage();
break;
case PAGE_ARMED:
showArmedPage();
break;
case PAGE_BATTERY: case PAGE_BATTERY:
showBatteryPage(); showBatteryPage();
break; break;
case PAGE_SENSORS: case PAGE_SENSORS:
showSensorsPage(); showSensorsPage();
break; break;
case PAGE_ARMED: case PAGE_RX:
showArmedPage(); showRxPage();
break; break;
} }
if (!armedState) { if (!armedState) {
@ -238,12 +316,31 @@ void updateDisplay(void)
} }
} }
void displayInit(rxConfig_t *rxConfigToUse)
void displayInit(void)
{ {
delay(20); delay(20);
ug2864hsweg01InitI2C(); ug2864hsweg01InitI2C();
rxConfig = rxConfigToUse;
memset(&pageState, 0, sizeof(pageState)); memset(&pageState, 0, sizeof(pageState));
pageState.pageId = PAGE_WELCOME;
updateDisplay();
displaySetNextPageChangeAt(micros() + (1000 * 1000 * 5));
}
void displaySetNextPageChangeAt(uint32_t futureMicros) {
pageState.nextPageAt = futureMicros;
}
void displayEnablePageCycling(void) {
pageState.pageFlags |= PAGE_STATE_FLAG_CYCLE_ENABLED;
}
void displayDisablePageCycling(void) {
pageState.pageFlags &= ~PAGE_STATE_FLAG_CYCLE_ENABLED;
} }
#endif #endif

View File

@ -17,3 +17,6 @@
void updateDisplay(void); void updateDisplay(void);
void displayEnablePageCycling(void);
void displayDisablePageCycling(void);
void displaySetNextPageChangeAt(uint32_t futureMicros);

View File

@ -24,6 +24,7 @@
#include <ctype.h> #include <ctype.h>
#include "platform.h" #include "platform.h"
#include "version.h"
#include "build_config.h" #include "build_config.h"
@ -1167,7 +1168,7 @@ static void cliVersion(char *cmdline)
{ {
UNUSED(cmdline); UNUSED(cmdline);
cliPrint("Cleanflight/" __TARGET__ " " __DATE__ " / " __TIME__ " (" __REVISION__ ")"); printf("Cleanflight/%s" __DATE__ " / " __TIME__ " (%s)", targetName, shortGitRevision);
} }
void cliProcess(void) void cliProcess(void)

View File

@ -52,6 +52,7 @@
#include "io/rc_controls.h" #include "io/rc_controls.h"
#include "io/gimbal.h" #include "io/gimbal.h"
#include "io/ledstrip.h" #include "io/ledstrip.h"
#include "io/display.h"
#include "sensors/sensors.h" #include "sensors/sensors.h"
#include "sensors/sonar.h" #include "sensors/sonar.h"
#include "sensors/barometer.h" #include "sensors/barometer.h"
@ -93,7 +94,7 @@ void gpsInit(serialConfig_t *serialConfig, gpsConfig_t *initialGpsConfig);
void navigationInit(gpsProfile_t *initialGpsProfile, pidProfile_t *pidProfile); void navigationInit(gpsProfile_t *initialGpsProfile, pidProfile_t *pidProfile);
bool sensorsAutodetect(sensorAlignmentConfig_t *sensorAlignmentConfig, uint16_t gyroLpf, uint8_t accHardwareToUse, int16_t magDeclinationFromConfig); bool sensorsAutodetect(sensorAlignmentConfig_t *sensorAlignmentConfig, uint16_t gyroLpf, uint8_t accHardwareToUse, int16_t magDeclinationFromConfig);
void imuInit(void); void imuInit(void);
void displayInit(void); void displayInit(rxConfig_t *intialRxConfig);
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, failsafe_t* failsafeToUse); void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, failsafe_t* failsafeToUse);
void loop(void); void loop(void);
@ -144,7 +145,7 @@ void init(void)
#ifdef DISPLAY #ifdef DISPLAY
if (feature(FEATURE_DISPLAY)) { if (feature(FEATURE_DISPLAY)) {
displayInit(); displayInit(&masterConfig.rxConfig);
} }
#endif #endif
@ -285,6 +286,12 @@ void init(void)
// Check battery type/voltage // Check battery type/voltage
if (feature(FEATURE_VBAT)) if (feature(FEATURE_VBAT))
batteryInit(&masterConfig.batteryConfig); batteryInit(&masterConfig.batteryConfig);
#ifdef DISPLAY
if (feature(FEATURE_DISPLAY)) {
displayEnablePageCycling();
}
#endif
} }
#ifdef SOFTSERIAL_LOOPBACK #ifdef SOFTSERIAL_LOOPBACK

19
src/main/version.c Normal file
View File

@ -0,0 +1,19 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
char *targetName = __TARGET__;
char *shortGitRevision = __REVISION__;

View File

@ -17,3 +17,5 @@
#define MW_VERSION 230 #define MW_VERSION 230
extern char* targetName;
extern char* shortGitRevision;