mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-22 15:55:48 +03:00
Merge pull request #1422 from jflyper/bfdev-osd-cms-separation-poc
Configuration Menu System (CMS)
This commit is contained in:
commit
04827440c8
58 changed files with 3602 additions and 1456 deletions
15
Makefile
15
Makefile
|
@ -491,6 +491,7 @@ COMMON_SRC = \
|
||||||
drivers/bus_i2c_soft.c \
|
drivers/bus_i2c_soft.c \
|
||||||
drivers/bus_spi.c \
|
drivers/bus_spi.c \
|
||||||
drivers/bus_spi_soft.c \
|
drivers/bus_spi_soft.c \
|
||||||
|
drivers/display.c \
|
||||||
drivers/exti.c \
|
drivers/exti.c \
|
||||||
drivers/gyro_sync.c \
|
drivers/gyro_sync.c \
|
||||||
drivers/io.c \
|
drivers/io.c \
|
||||||
|
@ -556,6 +557,14 @@ COMMON_SRC = \
|
||||||
HIGHEND_SRC = \
|
HIGHEND_SRC = \
|
||||||
blackbox/blackbox.c \
|
blackbox/blackbox.c \
|
||||||
blackbox/blackbox_io.c \
|
blackbox/blackbox_io.c \
|
||||||
|
cms/cms.c \
|
||||||
|
cms/cms_menu_blackbox.c \
|
||||||
|
cms/cms_menu_builtin.c \
|
||||||
|
cms/cms_menu_imu.c \
|
||||||
|
cms/cms_menu_ledstrip.c \
|
||||||
|
cms/cms_menu_misc.c \
|
||||||
|
cms/cms_menu_osd.c \
|
||||||
|
cms/cms_menu_vtx.c \
|
||||||
common/colorconversion.c \
|
common/colorconversion.c \
|
||||||
drivers/display_ug2864hsweg01.c \
|
drivers/display_ug2864hsweg01.c \
|
||||||
drivers/light_ws2811strip.c \
|
drivers/light_ws2811strip.c \
|
||||||
|
@ -565,9 +574,13 @@ HIGHEND_SRC = \
|
||||||
flight/gtune.c \
|
flight/gtune.c \
|
||||||
flight/navigation.c \
|
flight/navigation.c \
|
||||||
flight/gps_conversion.c \
|
flight/gps_conversion.c \
|
||||||
|
io/dashboard.c \
|
||||||
|
io/displayport_max7456.c \
|
||||||
|
io/displayport_msp.c \
|
||||||
|
io/displayport_oled.c \
|
||||||
io/gps.c \
|
io/gps.c \
|
||||||
io/ledstrip.c \
|
io/ledstrip.c \
|
||||||
io/dashboard.c \
|
io/osd.c \
|
||||||
sensors/sonar.c \
|
sensors/sonar.c \
|
||||||
sensors/barometer.c \
|
sensors/barometer.c \
|
||||||
telemetry/telemetry.c \
|
telemetry/telemetry.c \
|
||||||
|
|
871
src/main/cms/cms.c
Normal file
871
src/main/cms/cms.c
Normal file
|
@ -0,0 +1,871 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Original OSD code created by Marcin Baliniak
|
||||||
|
OSD-CMS separation by jflyper
|
||||||
|
CMS-displayPort separation by jflyper and martinbudden
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define CMS_MENU_DEBUG // For external menu content creators
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "build/debug.h"
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_menu_builtin.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
|
||||||
|
#include "common/typeconversion.h"
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
// For 'ARM' related
|
||||||
|
#include "fc/config.h"
|
||||||
|
#include "fc/rc_controls.h"
|
||||||
|
#include "fc/runtime_config.h"
|
||||||
|
|
||||||
|
// For rcData, stopAllMotors, stopPwmAllMotors
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
// For VISIBLE* (Actually, included by config_master.h)
|
||||||
|
#include "io/osd.h"
|
||||||
|
|
||||||
|
// DisplayPort management
|
||||||
|
|
||||||
|
#ifndef CMS_MAX_DEVICE
|
||||||
|
#define CMS_MAX_DEVICE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static displayPort_t *pCurrentDisplay;
|
||||||
|
|
||||||
|
static displayPort_t *cmsDisplayPorts[CMS_MAX_DEVICE];
|
||||||
|
static int cmsDeviceCount;
|
||||||
|
static int cmsCurrentDevice = -1;
|
||||||
|
|
||||||
|
bool cmsDisplayPortRegister(displayPort_t *pDisplay)
|
||||||
|
{
|
||||||
|
if (cmsDeviceCount == CMS_MAX_DEVICE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cmsDisplayPorts[cmsDeviceCount++] = pDisplay;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static displayPort_t *cmsDisplayPortSelectCurrent(void)
|
||||||
|
{
|
||||||
|
if (cmsDeviceCount == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (cmsCurrentDevice < 0)
|
||||||
|
cmsCurrentDevice = 0;
|
||||||
|
|
||||||
|
return cmsDisplayPorts[cmsCurrentDevice];
|
||||||
|
}
|
||||||
|
|
||||||
|
static displayPort_t *cmsDisplayPortSelectNext(void)
|
||||||
|
{
|
||||||
|
if (cmsDeviceCount == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cmsCurrentDevice = (cmsCurrentDevice + 1) % cmsDeviceCount; // -1 Okay
|
||||||
|
|
||||||
|
return cmsDisplayPorts[cmsCurrentDevice];
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CMS_UPDATE_INTERVAL_US 50000 // Interval of key scans (microsec)
|
||||||
|
#define CMS_POLL_INTERVAL_US 100000 // Interval of polling dynamic values (microsec)
|
||||||
|
|
||||||
|
// XXX LEFT_MENU_COLUMN and RIGHT_MENU_COLUMN must be adjusted
|
||||||
|
// dynamically depending on size of the active output device,
|
||||||
|
// or statically to accomodate sizes of all supported devices.
|
||||||
|
//
|
||||||
|
// Device characteristics
|
||||||
|
// OLED
|
||||||
|
// 21 cols x 8 rows
|
||||||
|
// 128x64 with 5x7 (6x8) : 21 cols x 8 rows
|
||||||
|
// MAX7456 (PAL)
|
||||||
|
// 30 cols x 16 rows
|
||||||
|
// MAX7456 (NTSC)
|
||||||
|
// 30 cols x 13 rows
|
||||||
|
// HoTT Telemetry Screen
|
||||||
|
// 21 cols x 8 rows
|
||||||
|
//
|
||||||
|
|
||||||
|
#define LEFT_MENU_COLUMN 1
|
||||||
|
#define RIGHT_MENU_COLUMN(p) ((p)->cols - 8)
|
||||||
|
#define MAX_MENU_ITEMS(p) ((p)->rows - 2)
|
||||||
|
|
||||||
|
static bool cmsInMenu = false;
|
||||||
|
|
||||||
|
STATIC_UNIT_TESTED const CMS_Menu *currentMenu; // Points to top entry of the current page
|
||||||
|
|
||||||
|
// XXX Does menu backing support backing into second page???
|
||||||
|
|
||||||
|
static const CMS_Menu *menuStack[10]; // Stack to save menu transition
|
||||||
|
static uint8_t menuStackHistory[10];// cursorRow in a stacked menu
|
||||||
|
static uint8_t menuStackIdx = 0;
|
||||||
|
|
||||||
|
static OSD_Entry *pageTop; // Points to top entry of the current page
|
||||||
|
static OSD_Entry *pageTopAlt; // Only 2 pages are allowed (for now)
|
||||||
|
static uint8_t maxRow; // Max row in the current page
|
||||||
|
|
||||||
|
static int8_t cursorRow;
|
||||||
|
|
||||||
|
#ifdef CMS_MENU_DEBUG // For external menu content creators
|
||||||
|
|
||||||
|
static char menuErrLabel[21 + 1] = "RANDOM DATA";
|
||||||
|
|
||||||
|
static OSD_Entry menuErrEntries[] = {
|
||||||
|
{ "BROKEN MENU", OME_Label, NULL, NULL, 0 },
|
||||||
|
{ menuErrLabel, OME_Label, NULL, NULL, 0 },
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu menuErr = {
|
||||||
|
"MENUERR",
|
||||||
|
OME_MENU,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
menuErrEntries,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stick/key detection
|
||||||
|
|
||||||
|
#define IS_HI(X) (rcData[X] > 1750)
|
||||||
|
#define IS_LO(X) (rcData[X] < 1250)
|
||||||
|
#define IS_MID(X) (rcData[X] > 1250 && rcData[X] < 1750)
|
||||||
|
|
||||||
|
//key definiotion because API provide menu navigation over MSP/GUI app - not used NOW
|
||||||
|
#define KEY_ENTER 0
|
||||||
|
#define KEY_UP 1
|
||||||
|
#define KEY_DOWN 2
|
||||||
|
#define KEY_LEFT 3
|
||||||
|
#define KEY_RIGHT 4
|
||||||
|
#define KEY_ESC 5
|
||||||
|
|
||||||
|
#define BUTTON_TIME 250 // msec
|
||||||
|
#define BUTTON_PAUSE 500 // msec
|
||||||
|
|
||||||
|
static void cmsUpdateMaxRow(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
maxRow = 0;
|
||||||
|
|
||||||
|
for (const OSD_Entry *ptr = pageTop; ptr->type != OME_END; ptr++) {
|
||||||
|
maxRow++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxRow > MAX_MENU_ITEMS(instance)) {
|
||||||
|
maxRow = MAX_MENU_ITEMS(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
maxRow--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsFormatFloat(int32_t value, char *floatString)
|
||||||
|
{
|
||||||
|
uint8_t k;
|
||||||
|
// np. 3450
|
||||||
|
|
||||||
|
itoa(100000 + value, floatString, 10); // Create string from abs of integer value
|
||||||
|
|
||||||
|
// 103450
|
||||||
|
|
||||||
|
floatString[0] = floatString[1];
|
||||||
|
floatString[1] = floatString[2];
|
||||||
|
floatString[2] = '.';
|
||||||
|
|
||||||
|
// 03.450
|
||||||
|
// usuwam koncowe zera i kropke
|
||||||
|
// Keep the first decimal place
|
||||||
|
for (k = 5; k > 3; k--)
|
||||||
|
if (floatString[k] == '0' || floatString[k] == '.')
|
||||||
|
floatString[k] = 0;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
// oraz zero wiodonce
|
||||||
|
if (floatString[0] == '0')
|
||||||
|
floatString[0] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsPadToSize(char *buf, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < size ; i++) {
|
||||||
|
if (buf[i] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; i < size ; i++) {
|
||||||
|
buf[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row)
|
||||||
|
{
|
||||||
|
char buff[10];
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
switch (p->type) {
|
||||||
|
case OME_String:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, p->data);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_Submenu:
|
||||||
|
case OME_Funcall:
|
||||||
|
if (IS_PRINTVALUE(p)) {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, ">");
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_Bool:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
if (*((uint8_t *)(p->data))) {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "YES");
|
||||||
|
} else {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "NO ");
|
||||||
|
}
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_TAB: {
|
||||||
|
if (IS_PRINTVALUE(p)) {
|
||||||
|
OSD_TAB_t *ptr = p->data;
|
||||||
|
//cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay) - 5, row, (char *)ptr->names[*ptr->val]);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, (char *)ptr->names[*ptr->val]);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef OSD
|
||||||
|
case OME_VISIBLE:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
uint32_t address = (uint32_t)p->data;
|
||||||
|
uint16_t *val;
|
||||||
|
|
||||||
|
val = (uint16_t *)address;
|
||||||
|
|
||||||
|
if (VISIBLE(*val)) {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "YES");
|
||||||
|
} else {
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "NO ");
|
||||||
|
}
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case OME_UINT8:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
OSD_UINT8_t *ptr = p->data;
|
||||||
|
itoa(*ptr->val, buff, 10);
|
||||||
|
cmsPadToSize(buff, 5);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, buff);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_INT8:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
OSD_INT8_t *ptr = p->data;
|
||||||
|
itoa(*ptr->val, buff, 10);
|
||||||
|
cmsPadToSize(buff, 5);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, buff);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_UINT16:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
OSD_UINT16_t *ptr = p->data;
|
||||||
|
itoa(*ptr->val, buff, 10);
|
||||||
|
cmsPadToSize(buff, 5);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, buff);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_INT16:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
OSD_UINT16_t *ptr = p->data;
|
||||||
|
itoa(*ptr->val, buff, 10);
|
||||||
|
cmsPadToSize(buff, 5);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, buff);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_FLOAT:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
OSD_FLOAT_t *ptr = p->data;
|
||||||
|
cmsFormatFloat(*ptr->val * ptr->multipler, buff);
|
||||||
|
cmsPadToSize(buff, 5);
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay) - 1, row, buff); // XXX One char left ???
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_Label:
|
||||||
|
if (IS_PRINTVALUE(p) && p->data) {
|
||||||
|
// A label with optional string, immediately following text
|
||||||
|
cnt = displayWrite(pDisplay, LEFT_MENU_COLUMN + 2 + strlen(p->text), row, p->data);
|
||||||
|
CLR_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_OSD_Exit:
|
||||||
|
case OME_END:
|
||||||
|
case OME_Back:
|
||||||
|
break;
|
||||||
|
case OME_MENU:
|
||||||
|
// Fall through
|
||||||
|
default:
|
||||||
|
#ifdef CMS_MENU_DEBUG
|
||||||
|
// Shouldn't happen. Notify creator of this menu content.
|
||||||
|
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "BADENT");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs)
|
||||||
|
{
|
||||||
|
if (!pageTop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
OSD_Entry *p;
|
||||||
|
uint8_t top = (pDisplay->rows - maxRow) / 2 - 1;
|
||||||
|
|
||||||
|
// Polled (dynamic) value display denominator.
|
||||||
|
|
||||||
|
bool drawPolled = false;
|
||||||
|
static uint32_t lastPolledUs = 0;
|
||||||
|
|
||||||
|
if (currentTimeUs > lastPolledUs + CMS_POLL_INTERVAL_US) {
|
||||||
|
drawPolled = true;
|
||||||
|
lastPolledUs = currentTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t room = displayTxBytesFree(pDisplay);
|
||||||
|
|
||||||
|
if (pDisplay->cleared) {
|
||||||
|
for (p = pageTop, i= 0; p->type != OME_END; p++, i++) {
|
||||||
|
SET_PRINTLABEL(p);
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > MAX_MENU_ITEMS(pDisplay)) // max per page
|
||||||
|
{
|
||||||
|
pageTopAlt = pageTop + MAX_MENU_ITEMS(pDisplay);
|
||||||
|
if (pageTopAlt->type == OME_END)
|
||||||
|
pageTopAlt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pDisplay->cleared = false;
|
||||||
|
} else if (drawPolled) {
|
||||||
|
for (p = pageTop ; p <= pageTop + maxRow ; p++) {
|
||||||
|
if (IS_DYNAMIC(p))
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cursor manipulation
|
||||||
|
|
||||||
|
while ((pageTop + cursorRow)->type == OME_Label) // skip label
|
||||||
|
cursorRow++;
|
||||||
|
|
||||||
|
if (pDisplay->cursorRow >= 0 && cursorRow != pDisplay->cursorRow) {
|
||||||
|
room -= displayWrite(pDisplay, LEFT_MENU_COLUMN, pDisplay->cursorRow + top, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (room < 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pDisplay->cursorRow != cursorRow) {
|
||||||
|
room -= displayWrite(pDisplay, LEFT_MENU_COLUMN, cursorRow + top, " >");
|
||||||
|
pDisplay->cursorRow = cursorRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (room < 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Print text labels
|
||||||
|
for (i = 0, p = pageTop; i < MAX_MENU_ITEMS(pDisplay) && p->type != OME_END; i++, p++) {
|
||||||
|
if (IS_PRINTLABEL(p)) {
|
||||||
|
uint8_t coloff = LEFT_MENU_COLUMN;
|
||||||
|
coloff += (p->type == OME_Label) ? 1 : 2;
|
||||||
|
room -= displayWrite(pDisplay, coloff, i + top, p->text);
|
||||||
|
CLR_PRINTLABEL(p);
|
||||||
|
if (room < 30)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print values
|
||||||
|
|
||||||
|
// XXX Polled values at latter positions in the list may not be
|
||||||
|
// XXX printed if not enough room in the middle of the list.
|
||||||
|
|
||||||
|
for (i = 0, p = pageTop; i < MAX_MENU_ITEMS(pDisplay) && p->type != OME_END; i++, p++) {
|
||||||
|
if (IS_PRINTVALUE(p)) {
|
||||||
|
room -= cmsDrawMenuEntry(pDisplay, p, top + i);
|
||||||
|
if (room < 30)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long cmsMenuChange(displayPort_t *pDisplay, const void *ptr)
|
||||||
|
{
|
||||||
|
CMS_Menu *pMenu = (CMS_Menu *)ptr;
|
||||||
|
|
||||||
|
if (pMenu) {
|
||||||
|
#ifdef CMS_MENU_DEBUG
|
||||||
|
if (pMenu->GUARD_type != OME_MENU) {
|
||||||
|
// ptr isn't pointing to a CMS_Menu.
|
||||||
|
if (pMenu->GUARD_type <= OME_MAX) {
|
||||||
|
strncpy(menuErrLabel, pMenu->GUARD_text, sizeof(menuErrLabel) - 1);
|
||||||
|
} else {
|
||||||
|
strncpy(menuErrLabel, "LABEL UNKNOWN", sizeof(menuErrLabel) - 1);
|
||||||
|
}
|
||||||
|
pMenu = &menuErr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stack the current menu and move to a new menu.
|
||||||
|
// The (pMenu == curretMenu) case occurs when reopening for display sw
|
||||||
|
|
||||||
|
if (pMenu != currentMenu) {
|
||||||
|
menuStack[menuStackIdx] = currentMenu;
|
||||||
|
cursorRow += pageTop - currentMenu->entries; // Convert cursorRow to absolute value
|
||||||
|
menuStackHistory[menuStackIdx] = cursorRow;
|
||||||
|
menuStackIdx++;
|
||||||
|
|
||||||
|
currentMenu = pMenu;
|
||||||
|
cursorRow = 0;
|
||||||
|
|
||||||
|
if (pMenu->onEnter)
|
||||||
|
pMenu->onEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
pageTop = currentMenu->entries;
|
||||||
|
pageTopAlt = NULL;
|
||||||
|
|
||||||
|
displayClear(pDisplay);
|
||||||
|
cmsUpdateMaxRow(pDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC_UNIT_TESTED long cmsMenuBack(displayPort_t *pDisplay)
|
||||||
|
{
|
||||||
|
// Let onExit function decide whether to allow exit or not.
|
||||||
|
|
||||||
|
if (currentMenu->onExit && currentMenu->onExit(pageTop + cursorRow) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (menuStackIdx) {
|
||||||
|
displayClear(pDisplay);
|
||||||
|
menuStackIdx--;
|
||||||
|
currentMenu = menuStack[menuStackIdx];
|
||||||
|
cursorRow = menuStackHistory[menuStackIdx];
|
||||||
|
|
||||||
|
// cursorRow is absolute offset of a focused entry when stacked.
|
||||||
|
// Convert it back to page and relative offset.
|
||||||
|
|
||||||
|
pageTop = currentMenu->entries; // Temporary for cmsUpdateMaxRow()
|
||||||
|
cmsUpdateMaxRow(pDisplay);
|
||||||
|
|
||||||
|
if (cursorRow > maxRow) {
|
||||||
|
// Cursor was in the second page.
|
||||||
|
pageTopAlt = currentMenu->entries;
|
||||||
|
pageTop = pageTopAlt + maxRow + 1;
|
||||||
|
cursorRow -= (maxRow + 1);
|
||||||
|
cmsUpdateMaxRow(pDisplay); // Update maxRow for the second page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC_UNIT_TESTED void cmsMenuOpen(void)
|
||||||
|
{
|
||||||
|
if (!cmsInMenu) {
|
||||||
|
// New open
|
||||||
|
pCurrentDisplay = cmsDisplayPortSelectCurrent();
|
||||||
|
if (!pCurrentDisplay)
|
||||||
|
return;
|
||||||
|
cmsInMenu = true;
|
||||||
|
currentMenu = &menuMain;
|
||||||
|
DISABLE_ARMING_FLAG(OK_TO_ARM);
|
||||||
|
} else {
|
||||||
|
// Switch display
|
||||||
|
displayPort_t *pNextDisplay = cmsDisplayPortSelectNext();
|
||||||
|
if (pNextDisplay != pCurrentDisplay) {
|
||||||
|
displayRelease(pCurrentDisplay);
|
||||||
|
pCurrentDisplay = pNextDisplay;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayGrab(pCurrentDisplay); // grab the display for use by the CMS
|
||||||
|
cmsMenuChange(pCurrentDisplay, currentMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsTraverseGlobalExit(const CMS_Menu *pMenu)
|
||||||
|
{
|
||||||
|
debug[0]++;
|
||||||
|
|
||||||
|
for (const OSD_Entry *p = pMenu->entries; p->type != OME_END ; p++) {
|
||||||
|
if (p->type == OME_Submenu) {
|
||||||
|
cmsTraverseGlobalExit(p->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pMenu->onGlobalExit) {
|
||||||
|
debug[1]++;
|
||||||
|
pMenu->onGlobalExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr) {
|
||||||
|
displayClear(pDisplay);
|
||||||
|
|
||||||
|
displayWrite(pDisplay, 5, 3, "REBOOTING...");
|
||||||
|
displayResync(pDisplay); // Was max7456RefreshAll(); why at this timing?
|
||||||
|
|
||||||
|
stopMotors();
|
||||||
|
stopPwmAllMotors();
|
||||||
|
delay(200);
|
||||||
|
|
||||||
|
cmsTraverseGlobalExit(&menuMain);
|
||||||
|
|
||||||
|
if (currentMenu->onExit)
|
||||||
|
currentMenu->onExit((OSD_Entry *)NULL); // Forced exit
|
||||||
|
|
||||||
|
saveConfigAndNotify();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsInMenu = false;
|
||||||
|
|
||||||
|
displayRelease(pDisplay);
|
||||||
|
currentMenu = NULL;
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
systemReset();
|
||||||
|
|
||||||
|
ENABLE_ARMING_FLAG(OK_TO_ARM);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key)
|
||||||
|
{
|
||||||
|
uint16_t res = BUTTON_TIME;
|
||||||
|
OSD_Entry *p;
|
||||||
|
|
||||||
|
if (!currentMenu)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (key == KEY_ESC) {
|
||||||
|
cmsMenuBack(pDisplay);
|
||||||
|
return BUTTON_PAUSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == KEY_DOWN) {
|
||||||
|
if (cursorRow < maxRow) {
|
||||||
|
cursorRow++;
|
||||||
|
} else {
|
||||||
|
if (pageTopAlt) { // we have another page
|
||||||
|
displayClear(pDisplay);
|
||||||
|
p = pageTopAlt;
|
||||||
|
pageTopAlt = pageTop;
|
||||||
|
pageTop = (OSD_Entry *)p;
|
||||||
|
cmsUpdateMaxRow(pDisplay);
|
||||||
|
}
|
||||||
|
cursorRow = 0; // Goto top in any case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == KEY_UP) {
|
||||||
|
cursorRow--;
|
||||||
|
|
||||||
|
if ((pageTop + cursorRow)->type == OME_Label && cursorRow > 0)
|
||||||
|
cursorRow--;
|
||||||
|
|
||||||
|
if (cursorRow == -1 || (pageTop + cursorRow)->type == OME_Label) {
|
||||||
|
if (pageTopAlt) {
|
||||||
|
displayClear(pDisplay);
|
||||||
|
p = pageTopAlt;
|
||||||
|
pageTopAlt = pageTop;
|
||||||
|
pageTop = (OSD_Entry *)p;
|
||||||
|
cmsUpdateMaxRow(pDisplay);
|
||||||
|
}
|
||||||
|
cursorRow = maxRow; // Goto bottom in any case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == KEY_DOWN || key == KEY_UP)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
p = pageTop + cursorRow;
|
||||||
|
|
||||||
|
switch (p->type) {
|
||||||
|
case OME_Submenu:
|
||||||
|
case OME_Funcall:
|
||||||
|
case OME_OSD_Exit:
|
||||||
|
if (p->func && key == KEY_RIGHT) {
|
||||||
|
p->func(pDisplay, p->data);
|
||||||
|
res = BUTTON_PAUSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_Back:
|
||||||
|
cmsMenuBack(pDisplay);
|
||||||
|
res = BUTTON_PAUSE;
|
||||||
|
break;
|
||||||
|
case OME_Bool:
|
||||||
|
if (p->data) {
|
||||||
|
uint8_t *val = p->data;
|
||||||
|
if (key == KEY_RIGHT)
|
||||||
|
*val = 1;
|
||||||
|
else
|
||||||
|
*val = 0;
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef OSD
|
||||||
|
case OME_VISIBLE:
|
||||||
|
if (p->data) {
|
||||||
|
uint32_t address = (uint32_t)p->data;
|
||||||
|
uint16_t *val;
|
||||||
|
|
||||||
|
val = (uint16_t *)address;
|
||||||
|
|
||||||
|
if (key == KEY_RIGHT)
|
||||||
|
*val |= VISIBLE_FLAG;
|
||||||
|
else
|
||||||
|
*val %= ~VISIBLE_FLAG;
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case OME_UINT8:
|
||||||
|
case OME_FLOAT:
|
||||||
|
if (p->data) {
|
||||||
|
OSD_UINT8_t *ptr = p->data;
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
|
if (*ptr->val < ptr->max)
|
||||||
|
*ptr->val += ptr->step;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*ptr->val > ptr->min)
|
||||||
|
*ptr->val -= ptr->step;
|
||||||
|
}
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
if (p->func) {
|
||||||
|
p->func(pDisplay, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_TAB:
|
||||||
|
if (p->type == OME_TAB) {
|
||||||
|
OSD_TAB_t *ptr = p->data;
|
||||||
|
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
|
if (*ptr->val < ptr->max)
|
||||||
|
*ptr->val += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*ptr->val > 0)
|
||||||
|
*ptr->val -= 1;
|
||||||
|
}
|
||||||
|
if (p->func)
|
||||||
|
p->func(pDisplay, p->data);
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_INT8:
|
||||||
|
if (p->data) {
|
||||||
|
OSD_INT8_t *ptr = p->data;
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
|
if (*ptr->val < ptr->max)
|
||||||
|
*ptr->val += ptr->step;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*ptr->val > ptr->min)
|
||||||
|
*ptr->val -= ptr->step;
|
||||||
|
}
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
if (p->func) {
|
||||||
|
p->func(pDisplay, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_UINT16:
|
||||||
|
if (p->data) {
|
||||||
|
OSD_UINT16_t *ptr = p->data;
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
|
if (*ptr->val < ptr->max)
|
||||||
|
*ptr->val += ptr->step;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*ptr->val > ptr->min)
|
||||||
|
*ptr->val -= ptr->step;
|
||||||
|
}
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
if (p->func) {
|
||||||
|
p->func(pDisplay, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_INT16:
|
||||||
|
if (p->data) {
|
||||||
|
OSD_INT16_t *ptr = p->data;
|
||||||
|
if (key == KEY_RIGHT) {
|
||||||
|
if (*ptr->val < ptr->max)
|
||||||
|
*ptr->val += ptr->step;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*ptr->val > ptr->min)
|
||||||
|
*ptr->val -= ptr->step;
|
||||||
|
}
|
||||||
|
SET_PRINTVALUE(p);
|
||||||
|
if (p->func) {
|
||||||
|
p->func(pDisplay, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OME_String:
|
||||||
|
break;
|
||||||
|
case OME_Label:
|
||||||
|
case OME_END:
|
||||||
|
break;
|
||||||
|
case OME_MENU:
|
||||||
|
// Shouldn't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsUpdate(uint32_t currentTimeUs)
|
||||||
|
{
|
||||||
|
static int16_t rcDelayMs = BUTTON_TIME;
|
||||||
|
static uint32_t lastCalledMs = 0;
|
||||||
|
static uint32_t lastCmsHeartBeatMs = 0;
|
||||||
|
|
||||||
|
const uint32_t currentTimeMs = currentTimeUs / 1000;
|
||||||
|
|
||||||
|
if (!cmsInMenu) {
|
||||||
|
// Detect menu invocation
|
||||||
|
if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||||
|
cmsMenuOpen();
|
||||||
|
rcDelayMs = BUTTON_PAUSE; // Tends to overshoot if BUTTON_TIME
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8_t key = 0;
|
||||||
|
if (rcDelayMs > 0) {
|
||||||
|
rcDelayMs -= (currentTimeMs - lastCalledMs);
|
||||||
|
}
|
||||||
|
else if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||||
|
// Double enter = display switching
|
||||||
|
cmsMenuOpen();
|
||||||
|
rcDelayMs = BUTTON_PAUSE;
|
||||||
|
}
|
||||||
|
else if (IS_HI(PITCH)) {
|
||||||
|
key = KEY_UP;
|
||||||
|
rcDelayMs = BUTTON_TIME;
|
||||||
|
}
|
||||||
|
else if (IS_LO(PITCH)) {
|
||||||
|
key = KEY_DOWN;
|
||||||
|
rcDelayMs = BUTTON_TIME;
|
||||||
|
}
|
||||||
|
else if (IS_LO(ROLL)) {
|
||||||
|
key = KEY_LEFT;
|
||||||
|
rcDelayMs = BUTTON_TIME;
|
||||||
|
}
|
||||||
|
else if (IS_HI(ROLL)) {
|
||||||
|
key = KEY_RIGHT;
|
||||||
|
rcDelayMs = BUTTON_TIME;
|
||||||
|
}
|
||||||
|
else if (IS_HI(YAW) || IS_LO(YAW))
|
||||||
|
{
|
||||||
|
key = KEY_ESC;
|
||||||
|
rcDelayMs = BUTTON_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
//lastCalled = currentTime;
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
rcDelayMs = cmsHandleKey(pCurrentDisplay, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsDrawMenu(pCurrentDisplay, currentTimeUs);
|
||||||
|
|
||||||
|
if (currentTimeMs > lastCmsHeartBeatMs + 500) {
|
||||||
|
// Heart beat for external CMS display device @ 500msec
|
||||||
|
// (Timeout @ 1000msec)
|
||||||
|
displayHeartbeat(pCurrentDisplay);
|
||||||
|
lastCmsHeartBeatMs = currentTimeMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastCalledMs = currentTimeMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmsHandler(uint32_t currentTime)
|
||||||
|
{
|
||||||
|
if (cmsDeviceCount < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static uint32_t lastCalled = 0;
|
||||||
|
|
||||||
|
if (currentTime >= lastCalled + CMS_UPDATE_INTERVAL_US) {
|
||||||
|
lastCalled = currentTime;
|
||||||
|
cmsUpdate(currentTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is initializing with menuMain better?
|
||||||
|
// Can it be done with the current main()?
|
||||||
|
void cmsInit(void)
|
||||||
|
{
|
||||||
|
cmsDeviceCount = 0;
|
||||||
|
cmsCurrentDevice = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CMS
|
17
src/main/cms/cms.h
Normal file
17
src/main/cms/cms.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "drivers/display.h"
|
||||||
|
|
||||||
|
// Device management
|
||||||
|
bool cmsDisplayPortRegister(displayPort_t *pDisplay);
|
||||||
|
|
||||||
|
// For main.c and scheduler
|
||||||
|
void cmsInit(void);
|
||||||
|
void cmsHandler(uint32_t currentTime);
|
||||||
|
|
||||||
|
long cmsMenuChange(displayPort_t *pPort, const void *ptr);
|
||||||
|
long cmsMenuExit(displayPort_t *pPort, const void *ptr);
|
||||||
|
|
||||||
|
#define CMS_STARTUP_HELP_TEXT1 "MENU: THR MID"
|
||||||
|
#define CMS_STARTUP_HELP_TEXT2 "+ YAW LEFT"
|
||||||
|
#define CMS_STARTUP_HELP_TEXT3 "+ PITCH UP"
|
111
src/main/cms/cms_menu_blackbox.c
Normal file
111
src/main/cms/cms_menu_blackbox.c
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// CMS things for blackbox and flashfs.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_blackbox.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
#include "io/flashfs.h"
|
||||||
|
|
||||||
|
#ifdef USE_FLASHFS
|
||||||
|
static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr)
|
||||||
|
{
|
||||||
|
UNUSED(ptr);
|
||||||
|
|
||||||
|
displayClear(pDisplay);
|
||||||
|
displayWrite(pDisplay, 5, 3, "ERASING FLASH...");
|
||||||
|
displayResync(pDisplay); // Was max7456RefreshAll(); Why at this timing?
|
||||||
|
|
||||||
|
flashfsEraseCompletely();
|
||||||
|
while (!flashfsIsReady()) {
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayClear(pDisplay);
|
||||||
|
displayResync(pDisplay); // Was max7456RefreshAll(); wedges during heavy SPI?
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif // USE_FLASHFS
|
||||||
|
|
||||||
|
static bool featureRead = false;
|
||||||
|
static uint8_t cmsx_FeatureBlackbox;
|
||||||
|
|
||||||
|
static long cmsx_Blackbox_FeatureRead(void)
|
||||||
|
{
|
||||||
|
if (!featureRead) {
|
||||||
|
cmsx_FeatureBlackbox = feature(FEATURE_BLACKBOX) ? 1 : 0;
|
||||||
|
featureRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_Blackbox_FeatureWriteback(void)
|
||||||
|
{
|
||||||
|
if (cmsx_FeatureBlackbox)
|
||||||
|
featureSet(FEATURE_BLACKBOX);
|
||||||
|
else
|
||||||
|
featureClear(FEATURE_BLACKBOX);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuBlackboxEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- BLACKBOX --", OME_Label, NULL, NULL, 0},
|
||||||
|
{ "ENABLED", OME_Bool, NULL, &cmsx_FeatureBlackbox, 0 },
|
||||||
|
{ "RATE DENOM", OME_UINT8, NULL, &(OSD_UINT8_t){ &masterConfig.blackbox_rate_denom,1,32,1 }, 0 },
|
||||||
|
|
||||||
|
#ifdef USE_FLASHFS
|
||||||
|
{ "ERASE FLASH", OME_Funcall, cmsx_EraseFlash, NULL, 0 },
|
||||||
|
#endif // USE_FLASHFS
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuBlackbox = {
|
||||||
|
.GUARD_text = "MENUBB",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_Blackbox_FeatureRead,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = cmsx_Blackbox_FeatureWriteback,
|
||||||
|
.entries = cmsx_menuBlackboxEntries
|
||||||
|
};
|
||||||
|
#endif
|
20
src/main/cms/cms_menu_blackbox.h
Normal file
20
src/main/cms/cms_menu_blackbox.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuBlackbox;
|
143
src/main/cms/cms_menu_builtin.c
Normal file
143
src/main/cms/cms_menu_builtin.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Built-in menu contents and support functions
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_builtin.h"
|
||||||
|
|
||||||
|
// Sub menus
|
||||||
|
|
||||||
|
#include "cms/cms_menu_imu.h"
|
||||||
|
#include "cms/cms_menu_blackbox.h"
|
||||||
|
#include "cms/cms_menu_vtx.h"
|
||||||
|
#include "cms/cms_menu_osd.h"
|
||||||
|
#include "cms/cms_menu_ledstrip.h"
|
||||||
|
#include "cms/cms_menu_misc.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Info
|
||||||
|
|
||||||
|
static char infoGitRev[GIT_SHORT_REVISION_LENGTH];
|
||||||
|
static char infoTargetName[] = __TARGET__;
|
||||||
|
|
||||||
|
#include "msp/msp_protocol.h" // XXX for FC identification... not available elsewhere
|
||||||
|
|
||||||
|
static long cmsx_InfoInit(void)
|
||||||
|
{
|
||||||
|
for (int i = 0 ; i < GIT_SHORT_REVISION_LENGTH ; i++) {
|
||||||
|
if (shortGitRevision[i] >= 'a' && shortGitRevision[i] <= 'f')
|
||||||
|
infoGitRev[i] = shortGitRevision[i] - 'a' + 'A';
|
||||||
|
else
|
||||||
|
infoGitRev[i] = shortGitRevision[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry menuInfoEntries[] = {
|
||||||
|
{ "--- INFO ---", OME_Label, NULL, NULL, 0 },
|
||||||
|
{ "FWID", OME_String, NULL, BETAFLIGHT_IDENTIFIER, 0 },
|
||||||
|
{ "FWVER", OME_String, NULL, FC_VERSION_STRING, 0 },
|
||||||
|
{ "GITREV", OME_String, NULL, infoGitRev, 0 },
|
||||||
|
{ "TARGET", OME_String, NULL, infoTargetName, 0 },
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu menuInfo = {
|
||||||
|
.GUARD_text = "MENUINFO",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_InfoInit,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = menuInfoEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
// Features
|
||||||
|
|
||||||
|
static OSD_Entry menuFeaturesEntries[] =
|
||||||
|
{
|
||||||
|
{"--- FEATURES ---", OME_Label, NULL, NULL, 0},
|
||||||
|
{"BLACKBOX", OME_Submenu, cmsMenuChange, &cmsx_menuBlackbox, 0},
|
||||||
|
#if defined(VTX) || defined(USE_RTC6705)
|
||||||
|
{"VTX", OME_Submenu, cmsMenuChange, &cmsx_menuVtx, 0},
|
||||||
|
#endif // VTX || USE_RTC6705
|
||||||
|
#ifdef LED_STRIP
|
||||||
|
{"LED STRIP", OME_Submenu, cmsMenuChange, &cmsx_menuLedstrip, 0},
|
||||||
|
#endif // LED_STRIP
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu menuFeatures = {
|
||||||
|
.GUARD_text = "MENUFEATURES",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = menuFeaturesEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main
|
||||||
|
|
||||||
|
static OSD_Entry menuMainEntries[] =
|
||||||
|
{
|
||||||
|
{"-- MAIN --", OME_Label, NULL, NULL, 0},
|
||||||
|
|
||||||
|
{"PROFILE", OME_Submenu, cmsMenuChange, &cmsx_menuImu, 0},
|
||||||
|
{"FEATURES", OME_Submenu, cmsMenuChange, &menuFeatures, 0},
|
||||||
|
#ifdef OSD
|
||||||
|
{"SCR LAYOUT", OME_Submenu, cmsMenuChange, &cmsx_menuOsdLayout, 0},
|
||||||
|
{"ALARMS", OME_Submenu, cmsMenuChange, &cmsx_menuAlarms, 0},
|
||||||
|
#endif
|
||||||
|
{"FC&FW INFO", OME_Submenu, cmsMenuChange, &menuInfo, 0},
|
||||||
|
{"MISC", OME_Submenu, cmsMenuChange, &cmsx_menuMisc, 0},
|
||||||
|
{"SAVE&REBOOT", OME_OSD_Exit, cmsMenuExit, (void*)1, 0},
|
||||||
|
{"EXIT", OME_OSD_Exit, cmsMenuExit, (void*)0, 0},
|
||||||
|
#ifdef CMS_MENU_DEBUG
|
||||||
|
{"ERR SAMPLE", OME_Submenu, cmsMenuChange, &menuInfoEntries[0], 0},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{NULL,OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu menuMain = {
|
||||||
|
.GUARD_text = "MENUMAIN",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = menuMainEntries,
|
||||||
|
};
|
||||||
|
#endif
|
22
src/main/cms/cms_menu_builtin.h
Normal file
22
src/main/cms/cms_menu_builtin.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
|
||||||
|
extern CMS_Menu menuMain;
|
384
src/main/cms/cms_menu_imu.c
Normal file
384
src/main/cms/cms_menu_imu.c
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Menu contents for PID, RATES, RC preview, misc
|
||||||
|
// Should be part of the relevant .c file.
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
//#include "common/typeconversion.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_imu.h"
|
||||||
|
|
||||||
|
#include "fc/config.h"
|
||||||
|
#include "fc/rc_controls.h"
|
||||||
|
#include "fc/runtime_config.h"
|
||||||
|
|
||||||
|
#include "flight/pid.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// PID
|
||||||
|
//
|
||||||
|
static uint8_t tmpProfileIndex;
|
||||||
|
static uint8_t profileIndex;
|
||||||
|
static char profileIndexString[] = " p";
|
||||||
|
static uint8_t tempPid[3][3];
|
||||||
|
|
||||||
|
static uint8_t tmpRateProfileIndex;
|
||||||
|
static uint8_t rateProfileIndex;
|
||||||
|
static char rateProfileIndexString[] = " p-r";
|
||||||
|
static controlRateConfig_t rateProfile;
|
||||||
|
|
||||||
|
static long cmsx_menuImu_onEnter(void)
|
||||||
|
{
|
||||||
|
profileIndex = masterConfig.current_profile_index;
|
||||||
|
tmpProfileIndex = profileIndex + 1;
|
||||||
|
|
||||||
|
rateProfileIndex = masterConfig.profile[profileIndex].activeRateProfile;
|
||||||
|
tmpRateProfileIndex = rateProfileIndex + 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_menuImu_onExit(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
masterConfig.current_profile_index = profileIndex;
|
||||||
|
masterConfig.profile[profileIndex].activeRateProfile = rateProfileIndex;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_profileIndexOnChange(displayPort_t *displayPort, const void *ptr)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
UNUSED(ptr);
|
||||||
|
|
||||||
|
profileIndex = tmpProfileIndex - 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_rateProfileIndexOnChange(displayPort_t *displayPort, const void *ptr)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
UNUSED(ptr);
|
||||||
|
|
||||||
|
rateProfileIndex = tmpRateProfileIndex - 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_PidRead(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
tempPid[i][0] = masterConfig.profile[profileIndex].pidProfile.P8[i];
|
||||||
|
tempPid[i][1] = masterConfig.profile[profileIndex].pidProfile.I8[i];
|
||||||
|
tempPid[i][2] = masterConfig.profile[profileIndex].pidProfile.D8[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_PidOnEnter(void)
|
||||||
|
{
|
||||||
|
profileIndexString[1] = '0' + tmpProfileIndex;
|
||||||
|
cmsx_PidRead();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_PidWriteback(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.P8[i] = tempPid[i][0];
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.I8[i] = tempPid[i][1];
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.D8[i] = tempPid[i][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuPidEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- PID --", OME_Label, NULL, profileIndexString, 0},
|
||||||
|
|
||||||
|
{ "ROLL P", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDROLL][0], 0, 200, 1 }, 0 },
|
||||||
|
{ "ROLL I", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDROLL][1], 0, 200, 1 }, 0 },
|
||||||
|
{ "ROLL D", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDROLL][2], 0, 200, 1 }, 0 },
|
||||||
|
|
||||||
|
{ "PITCH P", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDPITCH][0], 0, 200, 1 }, 0 },
|
||||||
|
{ "PITCH I", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDPITCH][1], 0, 200, 1 }, 0 },
|
||||||
|
{ "PITCH D", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDPITCH][2], 0, 200, 1 }, 0 },
|
||||||
|
|
||||||
|
{ "YAW P", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDYAW][0], 0, 200, 1 }, 0 },
|
||||||
|
{ "YAW I", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDYAW][1], 0, 200, 1 }, 0 },
|
||||||
|
{ "YAW D", OME_UINT8, NULL, &(OSD_UINT8_t){ &tempPid[PIDYAW][2], 0, 200, 1 }, 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu cmsx_menuPid = {
|
||||||
|
.GUARD_text = "XPID",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_PidOnEnter,
|
||||||
|
.onExit = cmsx_PidWriteback,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuPidEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Rate & Expo
|
||||||
|
//
|
||||||
|
|
||||||
|
static long cmsx_RateProfileRead(void)
|
||||||
|
{
|
||||||
|
memcpy(&rateProfile, &masterConfig.profile[profileIndex].controlRateProfile[rateProfileIndex], sizeof(controlRateConfig_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_RateProfileWriteback(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
memcpy(&masterConfig.profile[profileIndex].controlRateProfile[rateProfileIndex], &rateProfile, sizeof(controlRateConfig_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_RateProfileOnEnter(void)
|
||||||
|
{
|
||||||
|
rateProfileIndexString[1] = '0' + tmpProfileIndex;
|
||||||
|
rateProfileIndexString[3] = '0' + tmpRateProfileIndex;
|
||||||
|
cmsx_RateProfileRead();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuRateProfileEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- RATE --", OME_Label, NULL, rateProfileIndexString, 0 },
|
||||||
|
|
||||||
|
{ "RC RATE", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rcRate8, 0, 255, 1, 10 }, 0 },
|
||||||
|
{ "RC YAW RATE", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rcYawRate8, 0, 255, 1, 10 }, 0 },
|
||||||
|
|
||||||
|
{ "ROLL SUPER", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rates[0], 0, 100, 1, 10 }, 0 },
|
||||||
|
{ "PITCH SUPER", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rates[1], 0, 100, 1, 10 }, 0 },
|
||||||
|
{ "YAW SUPER", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rates[2], 0, 100, 1, 10 }, 0 },
|
||||||
|
|
||||||
|
{ "RC EXPO", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rcExpo8, 0, 100, 1, 10 }, 0 },
|
||||||
|
{ "RC YAW EXP", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.rcYawExpo8, 0, 100, 1, 10 }, 0 },
|
||||||
|
|
||||||
|
{ "THRPID ATT", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &rateProfile.dynThrPID, 0, 100, 1, 10}, 0 },
|
||||||
|
{ "TPA BRKPT", OME_UINT16, NULL, &(OSD_UINT16_t){ &rateProfile.tpa_breakpoint, 1000, 2000, 10}, 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu cmsx_menuRateProfile = {
|
||||||
|
.GUARD_text = "MENURATE",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_RateProfileOnEnter,
|
||||||
|
.onExit = cmsx_RateProfileWriteback,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuRateProfileEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t cmsx_dtermSetpointWeight;
|
||||||
|
static uint8_t cmsx_setpointRelaxRatio;
|
||||||
|
static uint8_t cmsx_angleStrength;
|
||||||
|
static uint8_t cmsx_horizonStrength;
|
||||||
|
static uint8_t cmsx_horizonTransition;
|
||||||
|
|
||||||
|
static long cmsx_profileOtherOnEnter(void)
|
||||||
|
{
|
||||||
|
profileIndexString[1] = '0' + tmpProfileIndex;
|
||||||
|
|
||||||
|
cmsx_dtermSetpointWeight = masterConfig.profile[profileIndex].pidProfile.dtermSetpointWeight;
|
||||||
|
cmsx_setpointRelaxRatio = masterConfig.profile[profileIndex].pidProfile.setpointRelaxRatio;
|
||||||
|
|
||||||
|
cmsx_angleStrength = masterConfig.profile[profileIndex].pidProfile.P8[PIDLEVEL];
|
||||||
|
cmsx_horizonStrength = masterConfig.profile[profileIndex].pidProfile.I8[PIDLEVEL];
|
||||||
|
cmsx_horizonTransition = masterConfig.profile[profileIndex].pidProfile.D8[PIDLEVEL];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_profileOtherOnExit(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.dtermSetpointWeight = cmsx_dtermSetpointWeight;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.setpointRelaxRatio = cmsx_setpointRelaxRatio;
|
||||||
|
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.P8[PIDLEVEL] = cmsx_angleStrength;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.I8[PIDLEVEL] = cmsx_horizonStrength;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.D8[PIDLEVEL] = cmsx_horizonTransition;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuProfileOtherEntries[] = {
|
||||||
|
{ "-- OTHER PP --", OME_Label, NULL, profileIndexString, 0 },
|
||||||
|
|
||||||
|
{ "D SETPT WT", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_dtermSetpointWeight, 0, 255, 1, 10 }, 0 },
|
||||||
|
{ "SETPT TRS", OME_FLOAT, NULL, &(OSD_FLOAT_t) { &cmsx_setpointRelaxRatio, 0, 100, 1, 10 }, 0 },
|
||||||
|
{ "ANGLE STR", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_angleStrength, 0, 200, 1 } , 0 },
|
||||||
|
{ "HORZN STR", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_horizonStrength, 0, 200, 1 } , 0 },
|
||||||
|
{ "HORZN TRS", OME_UINT8, NULL, &(OSD_UINT8_t) { &cmsx_horizonTransition, 0, 200, 1 } , 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu cmsx_menuProfileOther = {
|
||||||
|
.GUARD_text = "XPROFOTHER",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_profileOtherOnEnter,
|
||||||
|
.onExit = cmsx_profileOtherOnExit,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuProfileOtherEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuFilterGlobalEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- FILTER GLB --", OME_Label, NULL, NULL, 0 },
|
||||||
|
|
||||||
|
{ "GYRO LPF", OME_UINT8, NULL, &(OSD_UINT8_t) { &masterConfig.gyro_soft_lpf_hz, 0, 255, 1 }, 0 },
|
||||||
|
{ "GYRO NF1", OME_UINT16, NULL, &(OSD_UINT16_t) { &masterConfig.gyro_soft_notch_hz_1, 0, 500, 1 }, 0 },
|
||||||
|
{ "GYRO NF1C", OME_UINT16, NULL, &(OSD_UINT16_t) { &masterConfig.gyro_soft_notch_cutoff_1, 0, 500, 1 }, 0 },
|
||||||
|
{ "GYRO NF2", OME_UINT16, NULL, &(OSD_UINT16_t) { &masterConfig.gyro_soft_notch_hz_2, 0, 500, 1 }, 0 },
|
||||||
|
{ "GYRO NF2C", OME_UINT16, NULL, &(OSD_UINT16_t) { &masterConfig.gyro_soft_notch_cutoff_2, 0, 500, 1 }, 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu cmsx_menuFilterGlobal = {
|
||||||
|
.GUARD_text = "XFLTGLB",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuFilterGlobalEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint16_t cmsx_dterm_lpf_hz;
|
||||||
|
static uint16_t cmsx_dterm_notch_hz;
|
||||||
|
static uint16_t cmsx_dterm_notch_cutoff;
|
||||||
|
static uint16_t cmsx_yaw_lpf_hz;
|
||||||
|
static uint16_t cmsx_yaw_p_limit;
|
||||||
|
|
||||||
|
static long cmsx_FilterPerProfileRead(void)
|
||||||
|
{
|
||||||
|
cmsx_dterm_lpf_hz = masterConfig.profile[profileIndex].pidProfile.dterm_lpf_hz;
|
||||||
|
cmsx_dterm_notch_hz = masterConfig.profile[profileIndex].pidProfile.dterm_notch_hz;
|
||||||
|
cmsx_dterm_notch_cutoff = masterConfig.profile[profileIndex].pidProfile.dterm_notch_cutoff;
|
||||||
|
cmsx_yaw_lpf_hz = masterConfig.profile[profileIndex].pidProfile.yaw_lpf_hz;
|
||||||
|
cmsx_yaw_p_limit = masterConfig.profile[profileIndex].pidProfile.yaw_p_limit;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_FilterPerProfileWriteback(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.dterm_lpf_hz = cmsx_dterm_lpf_hz;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.dterm_notch_hz = cmsx_dterm_notch_hz;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.dterm_notch_cutoff = cmsx_dterm_notch_cutoff;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.yaw_lpf_hz = cmsx_yaw_lpf_hz;
|
||||||
|
masterConfig.profile[profileIndex].pidProfile.yaw_p_limit = cmsx_yaw_p_limit;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuFilterPerProfileEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- FILTER PP --", OME_Label, NULL, NULL, 0 },
|
||||||
|
|
||||||
|
{ "DTERM LPF", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_dterm_lpf_hz, 0, 500, 1 }, 0 },
|
||||||
|
{ "DTERM NF", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_dterm_notch_hz, 0, 500, 1 }, 0 },
|
||||||
|
{ "DTERM NFCO", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_dterm_notch_cutoff, 0, 500, 1 }, 0 },
|
||||||
|
{ "YAW LPF", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_yaw_lpf_hz, 0, 500, 1 }, 0 },
|
||||||
|
{ "YAW P LIM", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_yaw_p_limit, 100, 500, 1 }, 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMS_Menu cmsx_menuFilterPerProfile = {
|
||||||
|
.GUARD_text = "XFLTPP",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_FilterPerProfileRead,
|
||||||
|
.onExit = cmsx_FilterPerProfileWriteback,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuFilterPerProfileEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuImuEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- IMU --", OME_Label, NULL, NULL, 0},
|
||||||
|
|
||||||
|
{"PID PROF", OME_UINT8, cmsx_profileIndexOnChange, &(OSD_UINT8_t){ &tmpProfileIndex, 1, MAX_PROFILE_COUNT, 1}, 0},
|
||||||
|
{"PID", OME_Submenu, cmsMenuChange, &cmsx_menuPid, 0},
|
||||||
|
{"OTHER PP", OME_Submenu, cmsMenuChange, &cmsx_menuProfileOther, 0},
|
||||||
|
|
||||||
|
{"RATE PROF", OME_UINT8, cmsx_rateProfileIndexOnChange, &(OSD_UINT8_t){ &tmpRateProfileIndex, 1, MAX_RATEPROFILES, 1}, 0},
|
||||||
|
{"RATE", OME_Submenu, cmsMenuChange, &cmsx_menuRateProfile, 0},
|
||||||
|
|
||||||
|
{"FLT PP", OME_Submenu, cmsMenuChange, &cmsx_menuFilterPerProfile, 0},
|
||||||
|
|
||||||
|
{"FLT GLB", OME_Submenu, cmsMenuChange, &cmsx_menuFilterGlobal, 0},
|
||||||
|
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuImu = {
|
||||||
|
.GUARD_text = "XIMU",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_menuImu_onEnter,
|
||||||
|
.onExit = cmsx_menuImu_onExit,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuImuEntries,
|
||||||
|
};
|
||||||
|
#endif // CMS
|
20
src/main/cms/cms_menu_imu.h
Normal file
20
src/main/cms/cms_menu_imu.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuImu;
|
82
src/main/cms/cms_menu_ledstrip.c
Normal file
82
src/main/cms/cms_menu_ledstrip.c
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_ledstrip.h"
|
||||||
|
|
||||||
|
#ifdef LED_STRIP
|
||||||
|
|
||||||
|
static bool featureRead = false;
|
||||||
|
static uint8_t cmsx_FeatureLedstrip;
|
||||||
|
|
||||||
|
static long cmsx_Ledstrip_FeatureRead(void)
|
||||||
|
{
|
||||||
|
if (!featureRead) {
|
||||||
|
cmsx_FeatureLedstrip = feature(FEATURE_LED_STRIP) ? 1 : 0;
|
||||||
|
featureRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_Ledstrip_FeatureWriteback(void)
|
||||||
|
{
|
||||||
|
if (cmsx_FeatureLedstrip)
|
||||||
|
featureSet(FEATURE_LED_STRIP);
|
||||||
|
else
|
||||||
|
featureClear(FEATURE_LED_STRIP);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuLedstripEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- LED STRIP --", OME_Label, NULL, NULL, 0 },
|
||||||
|
{ "ENABLED", OME_Bool, NULL, &cmsx_FeatureLedstrip, 0 },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuLedstrip = {
|
||||||
|
.GUARD_text = "MENULED",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_Ledstrip_FeatureRead,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = cmsx_Ledstrip_FeatureWriteback,
|
||||||
|
.entries = cmsx_menuLedstripEntries
|
||||||
|
};
|
||||||
|
#endif // LED_STRIP
|
||||||
|
#endif // CMS
|
20
src/main/cms/cms_menu_ledstrip.h
Normal file
20
src/main/cms/cms_menu_ledstrip.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuLedstrip;
|
104
src/main/cms/cms_menu_misc.c
Normal file
104
src/main/cms/cms_menu_misc.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_ledstrip.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Misc
|
||||||
|
//
|
||||||
|
|
||||||
|
static long cmsx_menuRcConfirmBack(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
if (self && self->type == OME_Back)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// RC preview
|
||||||
|
//
|
||||||
|
static OSD_Entry cmsx_menuRcEntries[] =
|
||||||
|
{
|
||||||
|
{ "-- RC PREV --", OME_Label, NULL, NULL, 0},
|
||||||
|
|
||||||
|
{ "ROLL", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[ROLL], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "PITCH", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[PITCH], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "THR", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[THROTTLE], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "YAW", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[YAW], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
|
||||||
|
{ "AUX1", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[AUX1], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "AUX2", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[AUX2], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "AUX3", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[AUX3], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
{ "AUX4", OME_INT16, NULL, &(OSD_INT16_t){ &rcData[AUX4], 1, 2500, 0 }, DYNAMIC },
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuRcPreview = {
|
||||||
|
.GUARD_text = "XRCPREV",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = cmsx_menuRcConfirmBack,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuRcEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static OSD_Entry menuMiscEntries[]=
|
||||||
|
{
|
||||||
|
{ "-- MISC --", OME_Label, NULL, NULL, 0 },
|
||||||
|
|
||||||
|
{ "MIN THR", OME_UINT16, NULL, &(OSD_UINT16_t){ &masterConfig.motorConfig.minthrottle, 1000, 2000, 1 }, 0 },
|
||||||
|
{ "VBAT SCALE", OME_UINT8, NULL, &(OSD_UINT8_t) { &masterConfig.batteryConfig.vbatscale, 1, 250, 1 }, 0 },
|
||||||
|
{ "VBAT CLMAX", OME_UINT8, NULL, &(OSD_UINT8_t) { &masterConfig.batteryConfig.vbatmaxcellvoltage, 10, 50, 1 }, 0 },
|
||||||
|
{ "RC PREV", OME_Submenu, cmsMenuChange, &cmsx_menuRcPreview, 0},
|
||||||
|
|
||||||
|
{ "BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{ NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuMisc = {
|
||||||
|
.GUARD_text = "XMISC",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = menuMiscEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CMS
|
20
src/main/cms/cms_menu_misc.h
Normal file
20
src/main/cms/cms_menu_misc.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuMisc;
|
112
src/main/cms/cms_menu_osd.c
Normal file
112
src/main/cms/cms_menu_osd.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_osd.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
#if defined(OSD) && defined(CMS)
|
||||||
|
|
||||||
|
OSD_UINT8_t entryAlarmRssi = {&masterConfig.osdProfile.rssi_alarm, 5, 90, 5};
|
||||||
|
OSD_UINT16_t entryAlarmCapacity = {&masterConfig.osdProfile.cap_alarm, 50, 30000, 50};
|
||||||
|
OSD_UINT16_t enryAlarmFlyTime = {&masterConfig.osdProfile.time_alarm, 1, 200, 1};
|
||||||
|
OSD_UINT16_t entryAlarmAltitude = {&masterConfig.osdProfile.alt_alarm, 1, 200, 1};
|
||||||
|
|
||||||
|
OSD_Entry cmsx_menuAlarmsEntries[] =
|
||||||
|
{
|
||||||
|
{"--- ALARMS ---", OME_Label, NULL, NULL, 0},
|
||||||
|
{"RSSI", OME_UINT8, NULL, &entryAlarmRssi, 0},
|
||||||
|
{"MAIN BAT", OME_UINT16, NULL, &entryAlarmCapacity, 0},
|
||||||
|
{"FLY TIME", OME_UINT16, NULL, &enryAlarmFlyTime, 0},
|
||||||
|
{"MAX ALT", OME_UINT16, NULL, &entryAlarmAltitude, 0},
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuAlarms = {
|
||||||
|
.GUARD_text = "MENUALARMS",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuAlarmsEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD_Entry menuOsdActiveElemsEntries[] =
|
||||||
|
{
|
||||||
|
{"--- ACTIV ELEM ---", OME_Label, NULL, NULL, 0},
|
||||||
|
{"RSSI", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE], 0},
|
||||||
|
{"MAIN BATTERY", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE], 0},
|
||||||
|
{"HORIZON", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON], 0},
|
||||||
|
{"HORIZON SIDEBARS", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS], 0},
|
||||||
|
{"UPTIME", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_ONTIME], 0},
|
||||||
|
{"FLY TIME", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_FLYTIME], 0},
|
||||||
|
{"FLY MODE", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_FLYMODE], 0},
|
||||||
|
{"NAME", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_CRAFT_NAME], 0},
|
||||||
|
{"THROTTLE", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS], 0},
|
||||||
|
#ifdef VTX
|
||||||
|
{"VTX CHAN", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_VTX_CHANNEL]},
|
||||||
|
#endif // VTX
|
||||||
|
{"CURRENT (A)", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_CURRENT_DRAW], 0},
|
||||||
|
{"USED MAH", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_MAH_DRAWN], 0},
|
||||||
|
#ifdef GPS
|
||||||
|
{"GPS SPEED", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_GPS_SPEED], 0},
|
||||||
|
{"GPS SATS.", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_GPS_SATS], 0},
|
||||||
|
#endif // GPS
|
||||||
|
{"ALTITUDE", OME_VISIBLE, NULL, &masterConfig.osdProfile.item_pos[OSD_ALTITUDE], 0},
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu menuOsdActiveElems = {
|
||||||
|
.GUARD_text = "MENUOSDACT",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = menuOsdActiveElemsEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD_Entry cmsx_menuOsdLayoutEntries[] =
|
||||||
|
{
|
||||||
|
{"---SCREEN LAYOUT---", OME_Label, NULL, NULL, 0},
|
||||||
|
{"ACTIVE ELEM", OME_Submenu, cmsMenuChange, &menuOsdActiveElems, 0},
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuOsdLayout = {
|
||||||
|
.GUARD_text = "MENULAYOUT",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = NULL,
|
||||||
|
.onExit = NULL,
|
||||||
|
.onGlobalExit = NULL,
|
||||||
|
.entries = cmsx_menuOsdLayoutEntries
|
||||||
|
};
|
||||||
|
#endif // CMS
|
21
src/main/cms/cms_menu_osd.h
Normal file
21
src/main/cms/cms_menu_osd.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuAlarms;
|
||||||
|
extern CMS_Menu cmsx_menuOsdLayout;
|
146
src/main/cms/cms_menu_vtx.c
Normal file
146
src/main/cms/cms_menu_vtx.c
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
#include "cms/cms_menu_vtx.h"
|
||||||
|
|
||||||
|
#include "config/config_profile.h"
|
||||||
|
#include "config/config_master.h"
|
||||||
|
#include "config/feature.h"
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
|
||||||
|
#if defined(VTX) || defined(USE_RTC6705)
|
||||||
|
|
||||||
|
static bool featureRead = false;
|
||||||
|
static uint8_t cmsx_featureVtx = 0, cmsx_vtxBand, cmsx_vtxChannel;
|
||||||
|
|
||||||
|
static long cmsx_Vtx_FeatureRead(void)
|
||||||
|
{
|
||||||
|
if (!featureRead) {
|
||||||
|
cmsx_featureVtx = feature(FEATURE_VTX) ? 1 : 0;
|
||||||
|
featureRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_Vtx_FeatureWriteback(void)
|
||||||
|
{
|
||||||
|
if (cmsx_featureVtx)
|
||||||
|
featureSet(FEATURE_VTX);
|
||||||
|
else
|
||||||
|
featureClear(FEATURE_VTX);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * const vtxBandNames[] = {
|
||||||
|
"BOSCAM A",
|
||||||
|
"BOSCAM B",
|
||||||
|
"BOSCAM E",
|
||||||
|
"FATSHARK",
|
||||||
|
"RACEBAND",
|
||||||
|
};
|
||||||
|
|
||||||
|
static OSD_TAB_t entryVtxBand = {&cmsx_vtxBand,4,&vtxBandNames[0]};
|
||||||
|
static OSD_UINT8_t entryVtxChannel = {&cmsx_vtxChannel, 1, 8, 1};
|
||||||
|
|
||||||
|
static void cmsx_Vtx_ConfigRead(void)
|
||||||
|
{
|
||||||
|
#ifdef VTX
|
||||||
|
cmsx_vtxBand = masterConfig.vtx_band;
|
||||||
|
cmsx_vtxChannel = masterConfig.vtx_channel + 1;
|
||||||
|
#endif // VTX
|
||||||
|
|
||||||
|
#ifdef USE_RTC6705
|
||||||
|
cmsx_vtxBand = masterConfig.vtx_channel / 8;
|
||||||
|
cmsx_vtxChannel = masterConfig.vtx_channel % 8 + 1;
|
||||||
|
#endif // USE_RTC6705
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmsx_Vtx_ConfigWriteback(void)
|
||||||
|
{
|
||||||
|
#ifdef VTX
|
||||||
|
masterConfig.vtx_band = cmsx_vtxBand;
|
||||||
|
masterConfig.vtx_channel = cmsx_vtxChannel - 1;
|
||||||
|
#endif // VTX
|
||||||
|
|
||||||
|
#ifdef USE_RTC6705
|
||||||
|
masterConfig.vtx_channel = cmsx_vtxBand * 8 + cmsx_vtxChannel - 1;
|
||||||
|
#endif // USE_RTC6705
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_Vtx_onEnter(void)
|
||||||
|
{
|
||||||
|
cmsx_Vtx_FeatureRead();
|
||||||
|
cmsx_Vtx_ConfigRead();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long cmsx_Vtx_onExit(const OSD_Entry *self)
|
||||||
|
{
|
||||||
|
UNUSED(self);
|
||||||
|
|
||||||
|
cmsx_Vtx_ConfigWriteback();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VTX
|
||||||
|
static OSD_UINT8_t entryVtxMode = {&masterConfig.vtx_mode, 0, 2, 1};
|
||||||
|
static OSD_UINT16_t entryVtxMhz = {&masterConfig.vtx_mhz, 5600, 5950, 1};
|
||||||
|
#endif // VTX
|
||||||
|
|
||||||
|
static OSD_Entry cmsx_menuVtxEntries[] =
|
||||||
|
{
|
||||||
|
{"--- VTX ---", OME_Label, NULL, NULL, 0},
|
||||||
|
{"ENABLED", OME_Bool, NULL, &cmsx_featureVtx, 0},
|
||||||
|
#ifdef VTX
|
||||||
|
{"VTX MODE", OME_UINT8, NULL, &entryVtxMode, 0},
|
||||||
|
{"VTX MHZ", OME_UINT16, NULL, &entryVtxMhz, 0},
|
||||||
|
#endif // VTX
|
||||||
|
{"BAND", OME_TAB, NULL, &entryVtxBand, 0},
|
||||||
|
{"CHANNEL", OME_UINT8, NULL, &entryVtxChannel, 0},
|
||||||
|
#ifdef USE_RTC6705
|
||||||
|
{"LOW POWER", OME_Bool, NULL, &masterConfig.vtx_power, 0},
|
||||||
|
#endif // USE_RTC6705
|
||||||
|
{"BACK", OME_Back, NULL, NULL, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
CMS_Menu cmsx_menuVtx = {
|
||||||
|
.GUARD_text = "MENUVTX",
|
||||||
|
.GUARD_type = OME_MENU,
|
||||||
|
.onEnter = cmsx_Vtx_onEnter,
|
||||||
|
.onExit= cmsx_Vtx_onExit,
|
||||||
|
.onGlobalExit = cmsx_Vtx_FeatureWriteback,
|
||||||
|
.entries = cmsx_menuVtxEntries
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VTX || USE_RTC6705
|
||||||
|
#endif // CMS
|
20
src/main/cms/cms_menu_vtx.h
Normal file
20
src/main/cms/cms_menu_vtx.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern CMS_Menu cmsx_menuVtx;
|
155
src/main/cms/cms_types.h
Normal file
155
src/main/cms/cms_types.h
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Menu element types
|
||||||
|
// XXX Upon separation, all OME would be renamed to CME_ or similar.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//type of elements
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
OME_Label,
|
||||||
|
OME_Back,
|
||||||
|
OME_OSD_Exit,
|
||||||
|
OME_Submenu,
|
||||||
|
OME_Funcall,
|
||||||
|
OME_Bool,
|
||||||
|
OME_INT8,
|
||||||
|
OME_UINT8,
|
||||||
|
OME_UINT16,
|
||||||
|
OME_INT16,
|
||||||
|
OME_String,
|
||||||
|
OME_FLOAT, //only up to 255 value and cant be 2.55 or 25.5, just for PID's
|
||||||
|
//wlasciwosci elementow
|
||||||
|
#ifdef OSD
|
||||||
|
OME_VISIBLE,
|
||||||
|
#endif
|
||||||
|
OME_TAB,
|
||||||
|
OME_END,
|
||||||
|
|
||||||
|
// Debug aid
|
||||||
|
OME_MENU,
|
||||||
|
|
||||||
|
OME_MAX = OME_MENU
|
||||||
|
} OSD_MenuElement;
|
||||||
|
|
||||||
|
typedef long (*CMSEntryFuncPtr)(displayPort_t *displayPort, const void *ptr);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *text;
|
||||||
|
const OSD_MenuElement type;
|
||||||
|
const CMSEntryFuncPtr func;
|
||||||
|
void *data;
|
||||||
|
uint8_t flags;
|
||||||
|
} OSD_Entry;
|
||||||
|
|
||||||
|
// Bits in flags
|
||||||
|
#define PRINT_VALUE 0x01 // Value has been changed, need to redraw
|
||||||
|
#define PRINT_LABEL 0x02 // Text label should be printed
|
||||||
|
#define DYNAMIC 0x04 // Value should be updated dynamically
|
||||||
|
|
||||||
|
#define IS_PRINTVALUE(p) ((p)->flags & PRINT_VALUE)
|
||||||
|
#define SET_PRINTVALUE(p) { (p)->flags |= PRINT_VALUE; }
|
||||||
|
#define CLR_PRINTVALUE(p) { (p)->flags &= ~PRINT_VALUE; }
|
||||||
|
|
||||||
|
#define IS_PRINTLABEL(p) ((p)->flags & PRINT_LABEL)
|
||||||
|
#define SET_PRINTLABEL(p) { (p)->flags |= PRINT_LABEL; }
|
||||||
|
#define CLR_PRINTLABEL(p) { (p)->flags &= ~PRINT_LABEL; }
|
||||||
|
|
||||||
|
#define IS_DYNAMIC(p) ((p)->flags & DYNAMIC)
|
||||||
|
|
||||||
|
|
||||||
|
typedef long (*CMSMenuFuncPtr)(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
onExit function is called with self:
|
||||||
|
(1) Pointer to an OSD_Entry when cmsMenuBack() was called.
|
||||||
|
Point to an OSD_Entry with type == OME_Back if BACK was selected.
|
||||||
|
(2) NULL if called from menu exit (forced exit at top level).
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef long (*CMSMenuOnExitPtr)(const OSD_Entry *self);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// These two are debug aids for menu content creators.
|
||||||
|
const char *GUARD_text;
|
||||||
|
const OSD_MenuElement GUARD_type;
|
||||||
|
|
||||||
|
const CMSMenuFuncPtr onEnter;
|
||||||
|
const CMSMenuOnExitPtr onExit;
|
||||||
|
const CMSMenuFuncPtr onGlobalExit;
|
||||||
|
OSD_Entry *entries;
|
||||||
|
} CMS_Menu;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t *val;
|
||||||
|
uint8_t min;
|
||||||
|
uint8_t max;
|
||||||
|
uint8_t step;
|
||||||
|
} OSD_UINT8_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int8_t *val;
|
||||||
|
int8_t min;
|
||||||
|
int8_t max;
|
||||||
|
int8_t step;
|
||||||
|
} OSD_INT8_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int16_t *val;
|
||||||
|
int16_t min;
|
||||||
|
int16_t max;
|
||||||
|
int16_t step;
|
||||||
|
} OSD_INT16_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t *val;
|
||||||
|
uint16_t min;
|
||||||
|
uint16_t max;
|
||||||
|
uint16_t step;
|
||||||
|
} OSD_UINT16_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t *val;
|
||||||
|
uint8_t min;
|
||||||
|
uint8_t max;
|
||||||
|
uint8_t step;
|
||||||
|
uint16_t multipler;
|
||||||
|
} OSD_FLOAT_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t *val;
|
||||||
|
uint8_t max;
|
||||||
|
const char * const *names;
|
||||||
|
} OSD_TAB_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *val;
|
||||||
|
} OSD_String_t;
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include "config/config_profile.h"
|
#include "config/config_profile.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
|
||||||
#include "drivers/pwm_rx.h"
|
#include "drivers/pwm_rx.h"
|
||||||
#include "drivers/sound_beeper.h"
|
#include "drivers/sound_beeper.h"
|
||||||
#include "drivers/sonar_hcsr04.h"
|
#include "drivers/sonar_hcsr04.h"
|
||||||
|
|
72
src/main/drivers/display.c
Normal file
72
src/main/drivers/display.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
void displayClear(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
instance->vTable->clear(instance);
|
||||||
|
instance->cleared = true;
|
||||||
|
instance->cursorRow = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayGrab(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
instance->vTable->grab(instance);
|
||||||
|
instance->vTable->clear(instance);
|
||||||
|
instance->isGrabbed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayRelease(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
instance->vTable->release(instance);
|
||||||
|
instance->isGrabbed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool displayIsGrabbed(const displayPort_t *instance)
|
||||||
|
{
|
||||||
|
// can be called before initialised
|
||||||
|
return (instance && instance->isGrabbed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s)
|
||||||
|
{
|
||||||
|
return instance->vTable->write(instance, x, y, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayHeartbeat(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
instance->vTable->heartbeat(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayResync(displayPort_t *instance)
|
||||||
|
{
|
||||||
|
instance->vTable->resync(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t displayTxBytesFree(const displayPort_t *instance)
|
||||||
|
{
|
||||||
|
return instance->vTable->txBytesFree(instance);
|
||||||
|
}
|
||||||
|
|
49
src/main/drivers/display.h
Normal file
49
src/main/drivers/display.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct displayPortVTable_s;
|
||||||
|
typedef struct displayPort_s {
|
||||||
|
const struct displayPortVTable_s *vTable;
|
||||||
|
uint8_t rows;
|
||||||
|
uint8_t cols;
|
||||||
|
|
||||||
|
// CMS state
|
||||||
|
bool cleared;
|
||||||
|
int8_t cursorRow;
|
||||||
|
bool isGrabbed;
|
||||||
|
} displayPort_t;
|
||||||
|
|
||||||
|
typedef struct displayPortVTable_s {
|
||||||
|
int (*grab)(displayPort_t *displayPort);
|
||||||
|
int (*release)(displayPort_t *displayPort);
|
||||||
|
int (*clear)(displayPort_t *displayPort);
|
||||||
|
int (*write)(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *text);
|
||||||
|
int (*heartbeat)(displayPort_t *displayPort);
|
||||||
|
void (*resync)(displayPort_t *displayPort);
|
||||||
|
uint32_t (*txBytesFree)(const displayPort_t *displayPort);
|
||||||
|
} displayPortVTable_t;
|
||||||
|
|
||||||
|
void displayGrab(displayPort_t *instance);
|
||||||
|
void displayRelease(displayPort_t *instance);
|
||||||
|
bool displayIsGrabbed(const displayPort_t *instance);
|
||||||
|
void displayClear(displayPort_t *instance);
|
||||||
|
int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s);
|
||||||
|
void displayHeartbeat(displayPort_t *instance);
|
||||||
|
void displayResync(displayPort_t *instance);
|
||||||
|
uint16_t displayTxBytesFree(const displayPort_t *instance);
|
|
@ -294,7 +294,7 @@ void max7456WriteChar(uint8_t x, uint8_t y, uint8_t c)
|
||||||
screenBuffer[y*30+x] = c;
|
screenBuffer[y*30+x] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void max7456Write(uint8_t x, uint8_t y, char *buff)
|
void max7456Write(uint8_t x, uint8_t y, const char *buff)
|
||||||
{
|
{
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
for (i = 0; *(buff+i); i++)
|
for (i = 0; *(buff+i); i++)
|
||||||
|
@ -387,7 +387,7 @@ void max7456RefreshAll(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void max7456WriteNvm(uint8_t char_address, uint8_t *font_data)
|
void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data)
|
||||||
{
|
{
|
||||||
uint8_t x;
|
uint8_t x;
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,9 @@ extern uint16_t maxScreenSize;
|
||||||
|
|
||||||
void max7456Init(uint8_t system);
|
void max7456Init(uint8_t system);
|
||||||
void max7456DrawScreen(void);
|
void max7456DrawScreen(void);
|
||||||
void max7456WriteNvm(uint8_t char_address, uint8_t *font_data);
|
void max7456WriteNvm(uint8_t char_address, const uint8_t *font_data);
|
||||||
uint8_t max7456GetRowsCount(void);
|
uint8_t max7456GetRowsCount(void);
|
||||||
void max7456Write(uint8_t x, uint8_t y, char *buff);
|
void max7456Write(uint8_t x, uint8_t y, const char *buff);
|
||||||
void max7456WriteChar(uint8_t x, uint8_t y, uint8_t c);
|
void max7456WriteChar(uint8_t x, uint8_t y, uint8_t c);
|
||||||
void max7456ClearScreen(void);
|
void max7456ClearScreen(void);
|
||||||
void max7456RefreshAll(void);
|
void max7456RefreshAll(void);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include "blackbox/blackbox_io.h"
|
#include "blackbox/blackbox_io.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
#include "common/axis.h"
|
#include "common/axis.h"
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
|
@ -496,7 +498,7 @@ void createDefaultConfig(master_t *config)
|
||||||
|
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
intFeatureSet(FEATURE_OSD, config);
|
intFeatureSet(FEATURE_OSD, config);
|
||||||
resetOsdConfig(&config->osdProfile);
|
osdResetConfig(&config->osdProfile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BOARD_HAS_VOLTAGE_DIVIDER
|
#ifdef BOARD_HAS_VOLTAGE_DIVIDER
|
||||||
|
|
|
@ -62,9 +62,7 @@
|
||||||
#include "io/flashfs.h"
|
#include "io/flashfs.h"
|
||||||
#include "io/transponder_ir.h"
|
#include "io/transponder_ir.h"
|
||||||
#include "io/asyncfatfs/asyncfatfs.h"
|
#include "io/asyncfatfs/asyncfatfs.h"
|
||||||
#include "io/osd.h"
|
|
||||||
#include "io/serial_4way.h"
|
#include "io/serial_4way.h"
|
||||||
#include "io/vtx.h"
|
|
||||||
|
|
||||||
#include "msp/msp.h"
|
#include "msp/msp.h"
|
||||||
#include "msp/msp_protocol.h"
|
#include "msp/msp_protocol.h"
|
||||||
|
@ -1012,7 +1010,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
|
||||||
sbufWriteU16(dst, masterConfig.osdProfile.time_alarm);
|
sbufWriteU16(dst, masterConfig.osdProfile.time_alarm);
|
||||||
sbufWriteU16(dst, masterConfig.osdProfile.alt_alarm);
|
sbufWriteU16(dst, masterConfig.osdProfile.alt_alarm);
|
||||||
|
|
||||||
for (i = 0; i < OSD_MAX_ITEMS; i++) {
|
for (i = 0; i < OSD_ITEM_COUNT; i++) {
|
||||||
sbufWriteU16(dst, masterConfig.osdProfile.item_pos[i]);
|
sbufWriteU16(dst, masterConfig.osdProfile.item_pos[i]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
|
||||||
#include "common/axis.h"
|
#include "common/axis.h"
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
@ -264,7 +266,7 @@ static void taskTransponder(uint32_t currentTime)
|
||||||
static void taskUpdateOsd(uint32_t currentTime)
|
static void taskUpdateOsd(uint32_t currentTime)
|
||||||
{
|
{
|
||||||
if (feature(FEATURE_OSD)) {
|
if (feature(FEATURE_OSD)) {
|
||||||
updateOsd(currentTime);
|
osdUpdate(currentTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -329,6 +331,13 @@ void fcTasksInit(void)
|
||||||
#ifdef USE_BST
|
#ifdef USE_BST
|
||||||
setTaskEnabled(TASK_BST_MASTER_PROCESS, true);
|
setTaskEnabled(TASK_BST_MASTER_PROCESS, true);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CMS
|
||||||
|
#ifdef USE_MSP_DISPLAYPORT
|
||||||
|
setTaskEnabled(TASK_CMS, true);
|
||||||
|
#else
|
||||||
|
setTaskEnabled(TASK_CMS, feature(FEATURE_OSD) || feature(FEATURE_DASHBOARD));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
cfTask_t cfTasks[TASK_COUNT] = {
|
cfTask_t cfTasks[TASK_COUNT] = {
|
||||||
|
@ -488,4 +497,13 @@ cfTask_t cfTasks[TASK_COUNT] = {
|
||||||
.staticPriority = TASK_PRIORITY_IDLE,
|
.staticPriority = TASK_PRIORITY_IDLE,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
[TASK_CMS] = {
|
||||||
|
.taskName = "CMS",
|
||||||
|
.taskFunc = cmsHandler,
|
||||||
|
.desiredPeriod = 1000000 / 60, // 60 Hz
|
||||||
|
.staticPriority = TASK_PRIORITY_LOW,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,14 +23,19 @@
|
||||||
|
|
||||||
#ifdef USE_DASHBOARD
|
#ifdef USE_DASHBOARD
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
#include "build/version.h"
|
#include "build/version.h"
|
||||||
#include "build/debug.h"
|
#include "build/debug.h"
|
||||||
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#include "drivers/system.h"
|
#include "drivers/system.h"
|
||||||
|
#include "drivers/display.h"
|
||||||
#include "drivers/display_ug2864hsweg01.h"
|
#include "drivers/display_ug2864hsweg01.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
|
||||||
#include "common/printf.h"
|
#include "common/printf.h"
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
#include "common/axis.h"
|
#include "common/axis.h"
|
||||||
|
@ -50,6 +55,8 @@
|
||||||
#include "flight/imu.h"
|
#include "flight/imu.h"
|
||||||
#include "flight/failsafe.h"
|
#include "flight/failsafe.h"
|
||||||
|
|
||||||
|
#include "io/displayport_oled.h"
|
||||||
|
|
||||||
#ifdef GPS
|
#ifdef GPS
|
||||||
#include "io/gps.h"
|
#include "io/gps.h"
|
||||||
#include "flight/navigation.h"
|
#include "flight/navigation.h"
|
||||||
|
@ -77,6 +84,7 @@ static uint32_t nextDisplayUpdateAt = 0;
|
||||||
static bool dashboardPresent = false;
|
static bool dashboardPresent = false;
|
||||||
|
|
||||||
static rxConfig_t *rxConfig;
|
static rxConfig_t *rxConfig;
|
||||||
|
static displayPort_t *displayPort;
|
||||||
|
|
||||||
#define PAGE_TITLE_LINE_COUNT 1
|
#define PAGE_TITLE_LINE_COUNT 1
|
||||||
|
|
||||||
|
@ -581,6 +589,12 @@ void dashboardUpdate(uint32_t currentTime)
|
||||||
{
|
{
|
||||||
static uint8_t previousArmedState = 0;
|
static uint8_t previousArmedState = 0;
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
if (displayIsGrabbed(displayPort)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const bool updateNow = (int32_t)(currentTime - nextDisplayUpdateAt) >= 0L;
|
const bool updateNow = (int32_t)(currentTime - nextDisplayUpdateAt) >= 0L;
|
||||||
if (!updateNow) {
|
if (!updateNow) {
|
||||||
return;
|
return;
|
||||||
|
@ -692,6 +706,11 @@ void dashboardInit(rxConfig_t *rxConfigToUse)
|
||||||
resetDisplay();
|
resetDisplay();
|
||||||
delay(200);
|
delay(200);
|
||||||
|
|
||||||
|
displayPort = displayPortOledInit();
|
||||||
|
#if defined(CMS)
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
#endif
|
||||||
|
|
||||||
rxConfig = rxConfigToUse;
|
rxConfig = rxConfigToUse;
|
||||||
|
|
||||||
memset(&pageState, 0, sizeof(pageState));
|
memset(&pageState, 0, sizeof(pageState));
|
||||||
|
@ -728,5 +747,4 @@ void dashboardDisablePageCycling(void)
|
||||||
{
|
{
|
||||||
pageState.pageFlags &= ~PAGE_STATE_FLAG_CYCLE_ENABLED;
|
pageState.pageFlags &= ~PAGE_STATE_FLAG_CYCLE_ENABLED;
|
||||||
}
|
}
|
||||||
|
#endif // USE_DASHBOARD
|
||||||
#endif
|
|
||||||
|
|
107
src/main/io/displayport_max7456.c
Normal file
107
src/main/io/displayport_max7456.c
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef OSD
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "config/config_master.h"
|
||||||
|
|
||||||
|
#include "drivers/display.h"
|
||||||
|
#include "drivers/max7456.h"
|
||||||
|
|
||||||
|
displayPort_t max7456DisplayPort; // Referenced from osd.c
|
||||||
|
|
||||||
|
extern uint16_t refreshTimeout;
|
||||||
|
|
||||||
|
static int grab(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
osdResetAlarms();
|
||||||
|
displayPort->isGrabbed = true;
|
||||||
|
refreshTimeout = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int release(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
displayPort->isGrabbed = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clearScreen(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
max7456ClearScreen();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
max7456Write(x, y, s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resync(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
max7456RefreshAll();
|
||||||
|
displayPort->rows = max7456GetRowsCount();
|
||||||
|
displayPort->cols = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int heartbeat(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t txBytesFree(const displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static displayPortVTable_t max7456VTable = {
|
||||||
|
.grab = grab,
|
||||||
|
.release = release,
|
||||||
|
.clear = clearScreen,
|
||||||
|
.write = write,
|
||||||
|
.heartbeat = heartbeat,
|
||||||
|
.resync = resync,
|
||||||
|
.txBytesFree = txBytesFree,
|
||||||
|
};
|
||||||
|
|
||||||
|
displayPort_t *max7456DisplayPortInit(void)
|
||||||
|
{
|
||||||
|
max7456DisplayPort.vTable = &max7456VTable;
|
||||||
|
max7456DisplayPort.isGrabbed = false;
|
||||||
|
resync(&max7456DisplayPort);
|
||||||
|
return &max7456DisplayPort;
|
||||||
|
}
|
||||||
|
#endif // OSD
|
20
src/main/io/displayport_max7456.h
Normal file
20
src/main/io/displayport_max7456.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
displayPort_t *max7456DisplayPortInit(void);
|
119
src/main/io/displayport_msp.c
Normal file
119
src/main/io/displayport_msp.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef USE_MSP_DISPLAYPORT
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "drivers/display.h"
|
||||||
|
#include "drivers/system.h"
|
||||||
|
|
||||||
|
#include "fc/fc_msp.h"
|
||||||
|
|
||||||
|
#include "msp/msp_protocol.h"
|
||||||
|
#include "msp/msp_serial.h"
|
||||||
|
|
||||||
|
static displayPort_t mspDisplayPort;
|
||||||
|
|
||||||
|
static int output(displayPort_t *displayPort, uint8_t cmd, const uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return mspSerialPush(cmd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int grab(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
const uint8_t subcmd[] = { 0 };
|
||||||
|
|
||||||
|
return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int heartbeat(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
return grab(displayPort); // ensure display is not released by MW OSD software
|
||||||
|
}
|
||||||
|
|
||||||
|
static int release(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
const uint8_t subcmd[] = { 1 };
|
||||||
|
|
||||||
|
return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clear(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
const uint8_t subcmd[] = { 2 };
|
||||||
|
|
||||||
|
return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *string)
|
||||||
|
{
|
||||||
|
#define MSP_OSD_MAX_STRING_LENGTH 30
|
||||||
|
uint8_t buf[MSP_OSD_MAX_STRING_LENGTH + 4];
|
||||||
|
|
||||||
|
int len = strlen(string);
|
||||||
|
if (len >= MSP_OSD_MAX_STRING_LENGTH) {
|
||||||
|
len = MSP_OSD_MAX_STRING_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[0] = 3;
|
||||||
|
buf[1] = row;
|
||||||
|
buf[2] = col;
|
||||||
|
buf[3] = 0;
|
||||||
|
memcpy(&buf[4], string, len);
|
||||||
|
|
||||||
|
return output(displayPort, MSP_DISPLAYPORT, buf, len + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resync(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
displayPort->rows = 13; // XXX Will reflect NTSC/PAL in the future
|
||||||
|
displayPort->cols = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t txBytesFree(const displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return mspSerialTxBytesFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const displayPortVTable_t mspDisplayPortVTable = {
|
||||||
|
.grab = grab,
|
||||||
|
.release = release,
|
||||||
|
.clear = clear,
|
||||||
|
.write = write,
|
||||||
|
.heartbeat = heartbeat,
|
||||||
|
.resync = resync,
|
||||||
|
.txBytesFree = txBytesFree
|
||||||
|
};
|
||||||
|
|
||||||
|
displayPort_t *displayPortMspInit(void)
|
||||||
|
{
|
||||||
|
mspDisplayPort.vTable = &mspDisplayPortVTable;
|
||||||
|
mspDisplayPort.isGrabbed = false;
|
||||||
|
resync(&mspDisplayPort);
|
||||||
|
return &mspDisplayPort;
|
||||||
|
}
|
||||||
|
#endif // USE_MSP_DISPLAYPORT
|
21
src/main/io/displayport_msp.h
Normal file
21
src/main/io/displayport_msp.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct displayPort_s;
|
||||||
|
struct displayPort_s *displayPortMspInit(void);
|
91
src/main/io/displayport_oled.c
Normal file
91
src/main/io/displayport_oled.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "drivers/display.h"
|
||||||
|
#include "drivers/display_ug2864hsweg01.h"
|
||||||
|
|
||||||
|
static displayPort_t oledDisplayPort;
|
||||||
|
|
||||||
|
static int oledGrab(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int oledRelease(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int oledClear(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
i2c_OLED_clear_display_quick();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int oledWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
i2c_OLED_set_xy(x, y);
|
||||||
|
i2c_OLED_send_string(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int oledHeartbeat(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void oledResync(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t oledTxBytesFree(const displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const displayPortVTable_t oledVTable = {
|
||||||
|
.grab = oledGrab,
|
||||||
|
.release = oledRelease,
|
||||||
|
.clear = oledClear,
|
||||||
|
.write = oledWrite,
|
||||||
|
.heartbeat = oledHeartbeat,
|
||||||
|
.resync = oledResync,
|
||||||
|
.txBytesFree = oledTxBytesFree
|
||||||
|
};
|
||||||
|
|
||||||
|
displayPort_t *displayPortOledInit(void)
|
||||||
|
{
|
||||||
|
oledDisplayPort.vTable = &oledVTable;
|
||||||
|
oledDisplayPort.rows = SCREEN_CHARACTER_ROW_COUNT;
|
||||||
|
oledDisplayPort.cols = SCREEN_CHARACTER_COLUMN_COUNT;
|
||||||
|
oledDisplayPort.isGrabbed = false;
|
||||||
|
return &oledDisplayPort;
|
||||||
|
}
|
20
src/main/io/displayport_oled.h
Normal file
20
src/main/io/displayport_oled.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
displayPort_t *displayPortOledInit(void);
|
|
@ -62,8 +62,6 @@
|
||||||
#include "io/gimbal.h"
|
#include "io/gimbal.h"
|
||||||
#include "io/serial.h"
|
#include "io/serial.h"
|
||||||
#include "io/gps.h"
|
#include "io/gps.h"
|
||||||
#include "io/osd.h"
|
|
||||||
#include "io/vtx.h"
|
|
||||||
|
|
||||||
#include "flight/failsafe.h"
|
#include "flight/failsafe.h"
|
||||||
#include "flight/mixer.h"
|
#include "flight/mixer.h"
|
||||||
|
|
1797
src/main/io/osd.c
1797
src/main/io/osd.c
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#define VISIBLE_FLAG 0x0800
|
||||||
|
#define BLINK_FLAG 0x0400
|
||||||
|
#define VISIBLE(x) (x & VISIBLE_FLAG)
|
||||||
|
#define BLINK(x) ((x & BLINK_FLAG) && blinkState)
|
||||||
|
#define BLINK_OFF(x) (x & ~BLINK_FLAG)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OSD_RSSI_VALUE,
|
OSD_RSSI_VALUE,
|
||||||
|
@ -36,16 +40,16 @@ typedef enum {
|
||||||
OSD_GPS_SPEED,
|
OSD_GPS_SPEED,
|
||||||
OSD_GPS_SATS,
|
OSD_GPS_SATS,
|
||||||
OSD_ALTITUDE,
|
OSD_ALTITUDE,
|
||||||
OSD_MAX_ITEMS, // MUST BE LAST
|
OSD_ITEM_COUNT // MUST BE LAST
|
||||||
} osd_items_t;
|
} osd_items_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OSD_UNIT_IMPERIAL,
|
OSD_UNIT_IMPERIAL,
|
||||||
OSD_UNIT_METRIC
|
OSD_UNIT_METRIC
|
||||||
} osd_unit_t;
|
} osd_unit_e;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct osd_profile_s {
|
||||||
uint16_t item_pos[OSD_MAX_ITEMS];
|
uint16_t item_pos[OSD_ITEM_COUNT];
|
||||||
|
|
||||||
// Alarms
|
// Alarms
|
||||||
uint8_t rssi_alarm;
|
uint8_t rssi_alarm;
|
||||||
|
@ -54,17 +58,12 @@ typedef struct {
|
||||||
uint16_t alt_alarm;
|
uint16_t alt_alarm;
|
||||||
|
|
||||||
uint8_t video_system;
|
uint8_t video_system;
|
||||||
osd_unit_t units;
|
uint8_t row_shiftdown;
|
||||||
|
|
||||||
|
osd_unit_e units;
|
||||||
} osd_profile_t;
|
} osd_profile_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int16_t max_speed;
|
|
||||||
int16_t min_voltage; // /10
|
|
||||||
int16_t max_current; // /10
|
|
||||||
int16_t min_rssi;
|
|
||||||
int16_t max_altitude;
|
|
||||||
} statistic_t;
|
|
||||||
|
|
||||||
void updateOsd(uint32_t currentTime);
|
|
||||||
void osdInit(void);
|
void osdInit(void);
|
||||||
void resetOsdConfig(osd_profile_t *osdProfile);
|
void osdResetConfig(osd_profile_t *osdProfile);
|
||||||
|
void osdResetAlarms(void);
|
||||||
|
void osdUpdate(uint32_t currentTime);
|
||||||
|
|
|
@ -35,6 +35,8 @@ uint8_t cliMode = 0;
|
||||||
#include "build/debug.h"
|
#include "build/debug.h"
|
||||||
#include "build/version.h"
|
#include "build/version.h"
|
||||||
|
|
||||||
|
#include "cms/cms.h"
|
||||||
|
|
||||||
#include "common/axis.h"
|
#include "common/axis.h"
|
||||||
#include "common/color.h"
|
#include "common/color.h"
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
|
@ -944,6 +946,7 @@ const clivalue_t valueTable[] = {
|
||||||
|
|
||||||
#ifdef OSD
|
#ifdef OSD
|
||||||
{ "osd_video_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.video_system, .config.minmax = { 0, 2 } },
|
{ "osd_video_system", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.video_system, .config.minmax = { 0, 2 } },
|
||||||
|
{ "osd_row_shiftdown", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.row_shiftdown, .config.minmax = { 0, 1 } },
|
||||||
{ "osd_units", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.osdProfile.units, .config.lookup = { TABLE_UNIT } },
|
{ "osd_units", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.osdProfile.units, .config.lookup = { TABLE_UNIT } },
|
||||||
|
|
||||||
{ "osd_rssi_alarm", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.rssi_alarm, .config.minmax = { 0, 100 } },
|
{ "osd_rssi_alarm", VAR_UINT8 | MASTER_VALUE, &masterConfig.osdProfile.rssi_alarm, .config.minmax = { 0, 100 } },
|
||||||
|
|
|
@ -29,8 +29,9 @@
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
#include "common/printf.h"
|
#include "common/printf.h"
|
||||||
|
|
||||||
#include "drivers/nvic.h"
|
#include "cms/cms.h"
|
||||||
|
|
||||||
|
#include "drivers/nvic.h"
|
||||||
#include "drivers/sensor.h"
|
#include "drivers/sensor.h"
|
||||||
#include "drivers/system.h"
|
#include "drivers/system.h"
|
||||||
#include "drivers/dma.h"
|
#include "drivers/dma.h"
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
#include "io/serial_cli.h"
|
#include "io/serial_cli.h"
|
||||||
#include "io/transponder_ir.h"
|
#include "io/transponder_ir.h"
|
||||||
#include "io/osd.h"
|
#include "io/osd.h"
|
||||||
|
#include "io/displayport_msp.h"
|
||||||
#include "io/vtx.h"
|
#include "io/vtx.h"
|
||||||
|
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
@ -395,6 +397,10 @@ void init(void)
|
||||||
|
|
||||||
initBoardAlignment(&masterConfig.boardAlignment);
|
initBoardAlignment(&masterConfig.boardAlignment);
|
||||||
|
|
||||||
|
#ifdef CMS
|
||||||
|
cmsInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_DASHBOARD
|
#ifdef USE_DASHBOARD
|
||||||
if (feature(FEATURE_DASHBOARD)) {
|
if (feature(FEATURE_DASHBOARD)) {
|
||||||
dashboardInit(&masterConfig.rxConfig);
|
dashboardInit(&masterConfig.rxConfig);
|
||||||
|
@ -454,6 +460,10 @@ void init(void)
|
||||||
mspFcInit();
|
mspFcInit();
|
||||||
mspSerialInit();
|
mspSerialInit();
|
||||||
|
|
||||||
|
#if defined(USE_MSP_DISPLAYPORT) && defined(CMS)
|
||||||
|
cmsDisplayPortRegister(displayPortMspInit());
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_CLI
|
#ifdef USE_CLI
|
||||||
cliInit(&masterConfig.serialConfig);
|
cliInit(&masterConfig.serialConfig);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -216,6 +216,9 @@
|
||||||
#define MSP_OSD_VIDEO_CONFIG 180
|
#define MSP_OSD_VIDEO_CONFIG 180
|
||||||
#define MSP_SET_OSD_VIDEO_CONFIG 181
|
#define MSP_SET_OSD_VIDEO_CONFIG 181
|
||||||
|
|
||||||
|
// External OSD displayport mode messages
|
||||||
|
#define MSP_DISPLAYPORT 182
|
||||||
|
|
||||||
//
|
//
|
||||||
// Multwii original MSP commands
|
// Multwii original MSP commands
|
||||||
//
|
//
|
||||||
|
|
|
@ -120,7 +120,7 @@ static uint8_t mspSerialChecksumBuf(uint8_t checksum, const uint8_t *data, int l
|
||||||
|
|
||||||
#define JUMBO_FRAME_SIZE_LIMIT 255
|
#define JUMBO_FRAME_SIZE_LIMIT 255
|
||||||
|
|
||||||
static void mspSerialEncode(mspPort_t *msp, mspPacket_t *packet)
|
static int mspSerialEncode(mspPort_t *msp, mspPacket_t *packet)
|
||||||
{
|
{
|
||||||
serialBeginWrite(msp->port);
|
serialBeginWrite(msp->port);
|
||||||
const int len = sbufBytesRemaining(&packet->buf);
|
const int len = sbufBytesRemaining(&packet->buf);
|
||||||
|
@ -140,6 +140,7 @@ static void mspSerialEncode(mspPort_t *msp, mspPacket_t *packet)
|
||||||
}
|
}
|
||||||
serialWrite(msp->port, checksum);
|
serialWrite(msp->port, checksum);
|
||||||
serialEndWrite(msp->port);
|
serialEndWrite(msp->port);
|
||||||
|
return sizeof(hdr) + len + 1; // header, data, and checksum
|
||||||
}
|
}
|
||||||
|
|
||||||
static mspPostProcessFnPtr mspSerialProcessReceivedCommand(mspPort_t *msp, mspProcessCommandFnPtr mspProcessCommandFn)
|
static mspPostProcessFnPtr mspSerialProcessReceivedCommand(mspPort_t *msp, mspProcessCommandFnPtr mspProcessCommandFn)
|
||||||
|
@ -211,3 +212,57 @@ void mspSerialInit(void)
|
||||||
mspSerialAllocatePorts();
|
mspSerialAllocatePorts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mspSerialPush(uint8_t cmd, const uint8_t *data, int datalen)
|
||||||
|
{
|
||||||
|
static uint8_t pushBuf[30];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mspPacket_t push = {
|
||||||
|
.buf = { .ptr = pushBuf, .end = ARRAYEND(pushBuf), },
|
||||||
|
.cmd = cmd,
|
||||||
|
.result = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
||||||
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
|
if (!mspPort->port) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Kludge!!! Avoid zombie VCP port (avoid VCP entirely for now)
|
||||||
|
if (mspPort->port->identifier == SERIAL_PORT_USB_VCP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sbufWriteData(&push.buf, data, datalen);
|
||||||
|
|
||||||
|
sbufSwitchToReader(&push.buf, pushBuf);
|
||||||
|
|
||||||
|
ret = mspSerialEncode(mspPort, &push);
|
||||||
|
}
|
||||||
|
return ret; // return the number of bytes written
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mspSerialTxBytesFree()
|
||||||
|
{
|
||||||
|
uint32_t ret = UINT32_MAX;
|
||||||
|
|
||||||
|
for (int portIndex = 0; portIndex < MAX_MSP_PORT_COUNT; portIndex++) {
|
||||||
|
mspPort_t * const mspPort = &mspPorts[portIndex];
|
||||||
|
if (!mspPort->port) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Kludge!!! Avoid zombie VCP port (avoid VCP entirely for now)
|
||||||
|
if (mspPort->port->identifier == SERIAL_PORT_USB_VCP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t bytesFree = serialTxBytesFree(mspPort->port);
|
||||||
|
if (bytesFree < ret) {
|
||||||
|
ret = bytesFree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -66,3 +66,5 @@ void mspSerialInit(void);
|
||||||
void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessCommandFnPtr mspProcessCommandFn);
|
void mspSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessCommandFnPtr mspProcessCommandFn);
|
||||||
void mspSerialAllocatePorts(void);
|
void mspSerialAllocatePorts(void);
|
||||||
void mspSerialReleasePortIfAllocated(struct serialPort_s *serialPort);
|
void mspSerialReleasePortIfAllocated(struct serialPort_s *serialPort);
|
||||||
|
int mspSerialPush(uint8_t cmd, const uint8_t *data, int datalen);
|
||||||
|
uint32_t mspSerialTxBytesFree(void);
|
||||||
|
|
|
@ -85,6 +85,9 @@ typedef enum {
|
||||||
#ifdef USE_BST
|
#ifdef USE_BST
|
||||||
TASK_BST_MASTER_PROCESS,
|
TASK_BST_MASTER_PROCESS,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CMS
|
||||||
|
TASK_CMS,
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Count of real tasks */
|
/* Count of real tasks */
|
||||||
TASK_COUNT,
|
TASK_COUNT,
|
||||||
|
|
|
@ -91,10 +91,20 @@
|
||||||
#define SPI1_MISO_PIN PA6
|
#define SPI1_MISO_PIN PA6
|
||||||
#define SPI1_MOSI_PIN PA7
|
#define SPI1_MOSI_PIN PA7
|
||||||
|
|
||||||
|
#define USE_DASHBOARD
|
||||||
|
|
||||||
|
// Configuratoin Menu System
|
||||||
|
#define CMS
|
||||||
|
#define CMS_MAX_DEVICE 4
|
||||||
|
|
||||||
|
// Use external display connected by MSP to run CMS
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
|
|
||||||
// OSD define info:
|
// OSD define info:
|
||||||
// feature name (includes source) -> MAX_OSD, used in target.mk
|
// feature name (includes source) -> MAX_OSD, used in target.mk
|
||||||
// include the osd code
|
// include the osd code
|
||||||
#define OSD
|
#define OSD
|
||||||
|
|
||||||
// include the max7456 driver
|
// include the max7456 driver
|
||||||
#define USE_MAX7456
|
#define USE_MAX7456
|
||||||
#define MAX7456_SPI_INSTANCE SPI1
|
#define MAX7456_SPI_INSTANCE SPI1
|
||||||
|
|
|
@ -9,9 +9,8 @@ TARGET_SRC = \
|
||||||
drivers/compass_ak8963.c \
|
drivers/compass_ak8963.c \
|
||||||
drivers/compass_ak8975.c \
|
drivers/compass_ak8975.c \
|
||||||
drivers/compass_hmc5883l.c \
|
drivers/compass_hmc5883l.c \
|
||||||
|
drivers/max7456.c \
|
||||||
drivers/serial_usb_vcp.c \
|
drivers/serial_usb_vcp.c \
|
||||||
drivers/transponder_ir.c \
|
drivers/transponder_ir.c \
|
||||||
drivers/transponder_ir_stm32f30x.c \
|
drivers/transponder_ir_stm32f30x.c \
|
||||||
io/transponder_ir.c \
|
io/transponder_ir.c
|
||||||
drivers/max7456.c \
|
|
||||||
io/osd.c
|
|
||||||
|
|
|
@ -70,6 +70,9 @@
|
||||||
//#define MAX7456_DMA_CHANNEL_RX DMA1_Stream0
|
//#define MAX7456_DMA_CHANNEL_RX DMA1_Stream0
|
||||||
//#define MAX7456_DMA_IRQ_HANDLER_ID DMA1_ST0_HANDLER
|
//#define MAX7456_DMA_IRQ_HANDLER_ID DMA1_ST0_HANDLER
|
||||||
|
|
||||||
|
#define CMS
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
|
|
||||||
//#define PITOT
|
//#define PITOT
|
||||||
//#define USE_PITOT_MS4525
|
//#define USE_PITOT_MS4525
|
||||||
//#define MS4525_BUS I2C_DEVICE_EXT
|
//#define MS4525_BUS I2C_DEVICE_EXT
|
||||||
|
|
|
@ -5,6 +5,5 @@ TARGET_SRC = \
|
||||||
drivers/accgyro_spi_mpu6000.c \
|
drivers/accgyro_spi_mpu6000.c \
|
||||||
drivers/barometer_ms5611.c \
|
drivers/barometer_ms5611.c \
|
||||||
drivers/compass_hmc5883l.c \
|
drivers/compass_hmc5883l.c \
|
||||||
drivers/max7456.c \
|
drivers/max7456.c
|
||||||
io/osd.c
|
|
||||||
|
|
||||||
|
|
|
@ -167,3 +167,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9) )
|
#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9) )
|
||||||
|
|
||||||
|
#define CMS
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
|
|
|
@ -137,8 +137,16 @@
|
||||||
//#define USE_QUAD_MIXER_ONLY
|
//#define USE_QUAD_MIXER_ONLY
|
||||||
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
||||||
|
|
||||||
|
#define USE_DASHBOARD
|
||||||
|
|
||||||
#define OSD
|
#define OSD
|
||||||
|
|
||||||
|
// Configuratoin Menu System
|
||||||
|
#define CMS
|
||||||
|
|
||||||
|
// Use external display connected by MSP to run CMS
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
|
|
||||||
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
|
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
|
||||||
|
|
||||||
#define USE_SERVOS
|
#define USE_SERVOS
|
||||||
|
|
|
@ -11,5 +11,4 @@ TARGET_SRC = \
|
||||||
drivers/compass_hmc5883l.c \
|
drivers/compass_hmc5883l.c \
|
||||||
drivers/flash_m25p16.c \
|
drivers/flash_m25p16.c \
|
||||||
drivers/vtx_soft_spi_rtc6705.c \
|
drivers/vtx_soft_spi_rtc6705.c \
|
||||||
drivers/max7456.c \
|
drivers/max7456.c
|
||||||
io/osd.c
|
|
||||||
|
|
|
@ -132,3 +132,10 @@
|
||||||
#define USABLE_TIMER_CHANNEL_COUNT 17
|
#define USABLE_TIMER_CHANNEL_COUNT 17
|
||||||
#define USED_TIMERS ( TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(15) | TIM_N(16) | TIM_N(17) )
|
#define USED_TIMERS ( TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(15) | TIM_N(16) | TIM_N(17) )
|
||||||
|
|
||||||
|
#define USE_DASHBOARD
|
||||||
|
|
||||||
|
// Configuratoin Menu System
|
||||||
|
#define CMS
|
||||||
|
|
||||||
|
// Use external display connected by MSP to run CMS
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
|
|
|
@ -120,6 +120,8 @@
|
||||||
#define MAX7456_SPI_INSTANCE SPI2
|
#define MAX7456_SPI_INSTANCE SPI2
|
||||||
#define MAX7456_SPI_CS_PIN SPI2_NSS_PIN
|
#define MAX7456_SPI_CS_PIN SPI2_NSS_PIN
|
||||||
|
|
||||||
|
#define CMS
|
||||||
|
|
||||||
//#define USE_SDCARD
|
//#define USE_SDCARD
|
||||||
//#define USE_SDCARD_SPI2
|
//#define USE_SDCARD_SPI2
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,5 +25,4 @@ TARGET_SRC = \
|
||||||
drivers/compass_ak8975.c \
|
drivers/compass_ak8975.c \
|
||||||
drivers/compass_hmc5883l.c \
|
drivers/compass_hmc5883l.c \
|
||||||
drivers/flash_m25p16.c \
|
drivers/flash_m25p16.c \
|
||||||
drivers/max7456.c \
|
drivers/max7456.c
|
||||||
io/osd.c
|
|
||||||
|
|
|
@ -55,7 +55,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (FLASH_SIZE > 128)
|
#if (FLASH_SIZE > 128)
|
||||||
|
#define CMS
|
||||||
#define USE_DASHBOARD
|
#define USE_DASHBOARD
|
||||||
|
#define USE_MSP_DISPLAYPORT
|
||||||
#define TELEMETRY_MAVLINK
|
#define TELEMETRY_MAVLINK
|
||||||
#else
|
#else
|
||||||
#define SKIP_CLI_COMMAND_HELP
|
#define SKIP_CLI_COMMAND_HELP
|
||||||
|
|
|
@ -61,8 +61,6 @@
|
||||||
#include "io/gps.h"
|
#include "io/gps.h"
|
||||||
#include "io/ledstrip.h"
|
#include "io/ledstrip.h"
|
||||||
#include "io/beeper.h"
|
#include "io/beeper.h"
|
||||||
#include "io/osd.h"
|
|
||||||
#include "io/vtx.h"
|
|
||||||
|
|
||||||
#include "rx/rx.h"
|
#include "rx/rx.h"
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,6 @@
|
||||||
#include "io/motors.h"
|
#include "io/motors.h"
|
||||||
#include "io/gps.h"
|
#include "io/gps.h"
|
||||||
#include "io/serial.h"
|
#include "io/serial.h"
|
||||||
#include "io/ledstrip.h"
|
|
||||||
#include "io/osd.h"
|
|
||||||
#include "io/vtx.h"
|
|
||||||
|
|
||||||
#include "sensors/boardalignment.h"
|
#include "sensors/boardalignment.h"
|
||||||
#include "sensors/sensors.h"
|
#include "sensors/sensors.h"
|
||||||
|
|
|
@ -110,6 +110,14 @@ $(OBJECT_DIR)/common/maths.o : \
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/common/maths.c -o $@
|
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/common/maths.c -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/common/typeconversion.o : \
|
||||||
|
$(USER_DIR)/common/typeconversion.c \
|
||||||
|
$(USER_DIR)/common/typeconversion.h \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/common/typeconversion.c -o $@
|
||||||
|
|
||||||
$(OBJECT_DIR)/common/filter.o : \
|
$(OBJECT_DIR)/common/filter.o : \
|
||||||
$(USER_DIR)/common/filter.c \
|
$(USER_DIR)/common/filter.c \
|
||||||
$(USER_DIR)/common/filter.h \
|
$(USER_DIR)/common/filter.h \
|
||||||
|
@ -574,6 +582,39 @@ $(OBJECT_DIR)/alignsensor_unittest : \
|
||||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/drivers/display.o : \
|
||||||
|
$(USER_DIR)/drivers/display.c \
|
||||||
|
$(USER_DIR)/drivers/display.h \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/drivers/display.c -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/cms/cms.o : \
|
||||||
|
$(USER_DIR)/cms/cms.c \
|
||||||
|
$(USER_DIR)/cms/cms.h \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/cms/cms.c -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/cms_unittest.o : \
|
||||||
|
$(TEST_DIR)/cms_unittest.cc \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/cms_unittest.cc -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/cms_unittest : \
|
||||||
|
$(OBJECT_DIR)/cms_unittest.o \
|
||||||
|
$(OBJECT_DIR)/common/typeconversion.o \
|
||||||
|
$(OBJECT_DIR)/drivers/display.o \
|
||||||
|
$(OBJECT_DIR)/cms/cms.o \
|
||||||
|
$(OBJECT_DIR)/gtest_main.a
|
||||||
|
|
||||||
|
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||||
|
|
||||||
|
|
||||||
## test : Build and run the Unit Tests
|
## test : Build and run the Unit Tests
|
||||||
test: $(TESTS:%=test-%)
|
test: $(TESTS:%=test-%)
|
||||||
|
|
||||||
|
|
207
src/test/unit/cms_unittest.cc
Normal file
207
src/test/unit/cms_unittest.cc
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define BARO
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "target.h"
|
||||||
|
#include "drivers/display.h"
|
||||||
|
#include "cms/cms.h"
|
||||||
|
#include "cms/cms_types.h"
|
||||||
|
void cmsMenuOpen(void);
|
||||||
|
long cmsMenuBack(displayPort_t *pDisplay);
|
||||||
|
uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key);
|
||||||
|
extern CMS_Menu *currentMenu; // Points to top entry of the current page
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "unittest_macros.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
static displayPort_t testDisplayPort;
|
||||||
|
static int displayPortTestGrab(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int displayPortTestRelease(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int displayPortTestClear(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int displayPortTestWrite(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
UNUSED(x);
|
||||||
|
UNUSED(y);
|
||||||
|
UNUSED(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int displayPortTestHeartbeat(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void displayPortTestResync(displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t displayPortTestTxBytesFree(const displayPort_t *displayPort)
|
||||||
|
{
|
||||||
|
UNUSED(displayPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const displayPortVTable_t testDisplayPortVTable = {
|
||||||
|
.grab = displayPortTestGrab,
|
||||||
|
.release = displayPortTestRelease,
|
||||||
|
.clear = displayPortTestClear,
|
||||||
|
.write = displayPortTestWrite,
|
||||||
|
.heartbeat = displayPortTestHeartbeat,
|
||||||
|
.resync = displayPortTestResync,
|
||||||
|
.txBytesFree = displayPortTestTxBytesFree
|
||||||
|
};
|
||||||
|
|
||||||
|
displayPort_t *displayPortTestInit(void)
|
||||||
|
{
|
||||||
|
testDisplayPort.vTable = &testDisplayPortVTable;
|
||||||
|
testDisplayPort.rows = 10;
|
||||||
|
testDisplayPort.cols = 40;
|
||||||
|
testDisplayPort.isGrabbed = false;
|
||||||
|
return &testDisplayPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsDisplayPortRegister)
|
||||||
|
{
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = displayPortTestInit();
|
||||||
|
for (int ii = 0; ii < CMS_MAX_DEVICE; ++ii) {
|
||||||
|
const bool registered = cmsDisplayPortRegister(displayPort);
|
||||||
|
EXPECT_EQ(true, registered);
|
||||||
|
}
|
||||||
|
const bool registered = cmsDisplayPortRegister(displayPort);
|
||||||
|
EXPECT_EQ(false, registered);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsMenuOpen)
|
||||||
|
{
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = displayPortTestInit();
|
||||||
|
displayGrab(displayPort);
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
|
||||||
|
cmsMenuOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsMenuExit0)
|
||||||
|
{
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = displayPortTestInit();
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
|
||||||
|
cmsMenuOpen();
|
||||||
|
long exit = cmsMenuExit(displayPort, (void*)0);
|
||||||
|
EXPECT_EQ(0, exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsMenuExit1)
|
||||||
|
{
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = displayPortTestInit();
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
|
||||||
|
cmsMenuOpen();
|
||||||
|
long exit = cmsMenuExit(displayPort, (void*)0);
|
||||||
|
EXPECT_EQ(0, exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsMenuBack)
|
||||||
|
{
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = displayPortTestInit();
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
|
||||||
|
cmsMenuOpen();
|
||||||
|
long exit = cmsMenuBack(displayPort);
|
||||||
|
EXPECT_EQ(0, exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CMSUnittest, TestCmsMenuKey)
|
||||||
|
{
|
||||||
|
#define KEY_ENTER 0
|
||||||
|
#define KEY_UP 1
|
||||||
|
#define KEY_DOWN 2
|
||||||
|
#define KEY_LEFT 3
|
||||||
|
#define KEY_RIGHT 4
|
||||||
|
#define KEY_ESC 5
|
||||||
|
#define BUTTON_TIME 250 // msec
|
||||||
|
#define BUTTON_PAUSE 500 // msec
|
||||||
|
cmsInit();
|
||||||
|
displayPort_t *displayPort = &testDisplayPort;
|
||||||
|
cmsDisplayPortRegister(displayPort);
|
||||||
|
|
||||||
|
cmsMenuOpen();
|
||||||
|
uint16_t result = cmsHandleKey(displayPort, KEY_ESC);
|
||||||
|
EXPECT_EQ(BUTTON_PAUSE, result);
|
||||||
|
}
|
||||||
|
// STUBS
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static OSD_Entry menuMainEntries[] =
|
||||||
|
{
|
||||||
|
{"-- MAIN MENU --", OME_Label, NULL, NULL, 0},
|
||||||
|
{"SAVE&REBOOT", OME_OSD_Exit, cmsMenuExit, (void*)1, 0},
|
||||||
|
{"EXIT", OME_OSD_Exit, cmsMenuExit, (void*)0, 0},
|
||||||
|
{NULL, OME_END, NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
CMS_Menu menuMain = {
|
||||||
|
"MENUMAIN",
|
||||||
|
OME_MENU,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
menuMainEntries,
|
||||||
|
};
|
||||||
|
uint8_t armingFlags;
|
||||||
|
int16_t debug[4];
|
||||||
|
int16_t rcData[18];
|
||||||
|
void delay(uint32_t) {}
|
||||||
|
uint32_t micros(void) { return 0; }
|
||||||
|
uint32_t millis(void) { return 0; }
|
||||||
|
void saveConfigAndNotify(void) {}
|
||||||
|
void stopMotors(void) {}
|
||||||
|
void stopPwmAllMotors(void) {}
|
||||||
|
void systemReset(void) {}
|
||||||
|
}
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define CMS
|
||||||
|
#define CMS_MAX_DEVICE 4
|
||||||
#define MAG
|
#define MAG
|
||||||
#define BARO
|
#define BARO
|
||||||
#define GPS
|
#define GPS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue