New UI continued
This commit is contained in:
+33
-6
@@ -21,8 +21,8 @@
|
||||
#include "opentx.h"
|
||||
|
||||
uint8_t s_curveChan;
|
||||
|
||||
int8_t * curveEnd[MAX_CURVES];
|
||||
|
||||
void loadCurves()
|
||||
{
|
||||
bool showWarning= false;
|
||||
@@ -94,8 +94,35 @@ void resetCustomCurveX(int8_t * points, int noPoints)
|
||||
}
|
||||
}
|
||||
|
||||
void curveReset(uint8_t index)
|
||||
{
|
||||
CurveHeader * curve = &g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
memclear(points, 5 + curve->points);
|
||||
|
||||
if (curve->type == CURVE_TYPE_CUSTOM)
|
||||
resetCustomCurveX(points, 5 + curve->points);
|
||||
|
||||
memclear(curve, sizeof(CurveHeader));
|
||||
}
|
||||
|
||||
void curveMirror(uint8_t index)
|
||||
{
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
for (int i = 0; i < 5 + curve.points; i++)
|
||||
points[i] = -points[i];
|
||||
}
|
||||
|
||||
bool isCurveUsed(uint8_t index)
|
||||
{
|
||||
return !is_memclear(&g_model.curves[index], sizeof(CurveHeader)) || !is_memclear(curveAddress(index), 5);
|
||||
}
|
||||
|
||||
#define CUSTOM_POINT_X(points, count, idx) ((idx)==0 ? -100 : (((idx)==(count)-1) ? 100 : points[(count)+(idx)-1]))
|
||||
int32_t compute_tangent(CurveInfo * crv, int8_t * points, int i)
|
||||
int32_t compute_tangent(CurveHeader * crv, int8_t * points, int i)
|
||||
{
|
||||
int32_t m=0;
|
||||
uint8_t num_points = crv->points + 5;
|
||||
@@ -166,7 +193,7 @@ int32_t compute_tangent(CurveInfo * crv, int8_t * points, int i)
|
||||
*/
|
||||
int16_t hermite_spline(int16_t x, uint8_t idx)
|
||||
{
|
||||
CurveInfo &crv = g_model.curves[idx];
|
||||
CurveHeader &crv = g_model.curves[idx];
|
||||
int8_t *points = curveAddress(idx);
|
||||
uint8_t count = crv.points+5;
|
||||
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
||||
@@ -211,7 +238,7 @@ int16_t hermite_spline(int16_t x, uint8_t idx)
|
||||
|
||||
int intpol(int x, uint8_t idx) // -100, -75, -50, -25, 0 ,25 ,50, 75, 100
|
||||
{
|
||||
CurveInfo & crv = g_model.curves[idx];
|
||||
CurveHeader & crv = g_model.curves[idx];
|
||||
int8_t * points = curveAddress(idx);
|
||||
uint8_t count = crv.points+5;
|
||||
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
||||
@@ -307,7 +334,7 @@ int applyCustomCurve(int x, uint8_t idx)
|
||||
if (idx >= MAX_CURVES)
|
||||
return 0;
|
||||
|
||||
CurveInfo & crv = g_model.curves[idx];
|
||||
CurveHeader & crv = g_model.curves[idx];
|
||||
if (crv.smooth)
|
||||
return hermite_spline(x, idx);
|
||||
else
|
||||
@@ -322,7 +349,7 @@ point_t getPoint(uint8_t index)
|
||||
point_t getPoint(uint8_t curveIndex, uint8_t index)
|
||||
{
|
||||
point_t result = {0, 0};
|
||||
CurveInfo & crv = g_model.curves[curveIndex];
|
||||
CurveHeader & crv = g_model.curves[curveIndex];
|
||||
int8_t * points = curveAddress(curveIndex);
|
||||
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
||||
uint8_t count = 5 + crv.points;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#ifndef _CURVES_H_
|
||||
#define _CURVES_H_
|
||||
|
||||
enum BaseCurves {
|
||||
CURVE_NONE,
|
||||
CURVE_X_GT0,
|
||||
CURVE_X_LT0,
|
||||
CURVE_ABS_X,
|
||||
CURVE_F_GT0,
|
||||
CURVE_F_LT0,
|
||||
CURVE_ABS_F,
|
||||
CURVE_BASE
|
||||
};
|
||||
|
||||
void curveReset(uint8_t index);
|
||||
void curveMirror(uint8_t index);
|
||||
bool isCurveUsed(uint8_t index);
|
||||
void loadCurves();
|
||||
int8_t * curveAddress(uint8_t idx);
|
||||
bool moveCurve(uint8_t index, int8_t shift);
|
||||
int8_t getCurveX(int noPoints, int point);
|
||||
void resetCustomCurveX(int8_t * points, int noPoints);
|
||||
point_t getPoint(uint8_t i);
|
||||
point_t getPoint(uint8_t curveIndex, uint8_t index);
|
||||
int applyCustomCurve(int x, uint8_t idx);
|
||||
int applyCurve(int x, CurveRef & curve);
|
||||
int applyCurrentCurve(int x);
|
||||
|
||||
#endif
|
||||
@@ -190,7 +190,7 @@ PACK(struct FlightModeData {
|
||||
* Curve structure
|
||||
*/
|
||||
|
||||
PACK(struct CurveData {
|
||||
PACK(struct CurveHeader {
|
||||
uint8_t type:1;
|
||||
uint8_t smooth:1;
|
||||
int8_t points:6; // describes number of points - 5
|
||||
@@ -580,7 +580,7 @@ PACK(struct ModelData {
|
||||
LimitData limitData[MAX_OUTPUT_CHANNELS];
|
||||
ExpoData expoData[MAX_EXPOS];
|
||||
|
||||
CurveData curves[MAX_CURVES];
|
||||
CurveHeader curves[MAX_CURVES];
|
||||
int8_t points[MAX_CURVE_POINTS];
|
||||
|
||||
LogicalSwitchData logicalSw[MAX_LOGICAL_SWITCHES];
|
||||
@@ -849,7 +849,7 @@ static inline void check_struct()
|
||||
CHKSIZE(FrSkyLineData, 4);
|
||||
CHKTYPE(union TelemetryScreenData, 24);
|
||||
CHKSIZE(ModelHeader, 12);
|
||||
CHKSIZE(CurveData, 4);
|
||||
CHKSIZE(CurveHeader, 4);
|
||||
#elif defined(PCBTARANIS)
|
||||
CHKSIZE(MixData, 20);
|
||||
CHKSIZE(ExpoData, 17);
|
||||
@@ -863,7 +863,7 @@ static inline void check_struct()
|
||||
CHKSIZE(FrSkyLineData, 6);
|
||||
CHKTYPE(union TelemetryScreenData, 24);
|
||||
CHKSIZE(ModelHeader, 24);
|
||||
CHKSIZE(CurveData, 4);
|
||||
CHKSIZE(CurveHeader, 4);
|
||||
#elif defined(PCBHORUS)
|
||||
CHKSIZE(MixData, 20);
|
||||
CHKSIZE(ExpoData, 17);
|
||||
@@ -873,7 +873,7 @@ static inline void check_struct()
|
||||
CHKSIZE(TimerData, 16);
|
||||
CHKSIZE(SwashRingData, 8);
|
||||
CHKSIZE(ModelHeader, 31);
|
||||
CHKSIZE(CurveData, 4);
|
||||
CHKSIZE(CurveHeader, 4);
|
||||
CHKSIZE(CustomScreenData, 610);
|
||||
CHKSIZE(Topbar::PersistentData, 216);
|
||||
#elif defined(PCBNV14)
|
||||
@@ -889,7 +889,7 @@ static inline void check_struct()
|
||||
CHKSIZE(FrSkyBarData, 5);
|
||||
CHKSIZE(FrSkyLineData, 2);
|
||||
CHKSIZE(ModelHeader, 12);
|
||||
CHKTYPE(CurveData, 4);
|
||||
CHKTYPE(CurveHeader, 4);
|
||||
#else
|
||||
// Common for all variants
|
||||
CHKSIZE(LimitData, 5);
|
||||
@@ -897,7 +897,7 @@ static inline void check_struct()
|
||||
CHKSIZE(FrSkyBarData, 3);
|
||||
CHKSIZE(FrSkyLineData, 2);
|
||||
CHKSIZE(ModelHeader, 11);
|
||||
CHKTYPE(CurveData, 1);
|
||||
CHKTYPE(CurveHeader, 1);
|
||||
|
||||
CHKSIZE(MixData, 9);
|
||||
CHKSIZE(ExpoData, 4);
|
||||
|
||||
@@ -50,7 +50,7 @@ void runPopupCurvePreset(event_t event)
|
||||
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
int k = 25 * reusableBuffer.curveEdit.preset;
|
||||
int dx = 2000 / (5+crv.points-1);
|
||||
@@ -71,13 +71,13 @@ void onCurveOneMenu(const char * result)
|
||||
POPUP_INPUT(STR_PRESET, runPopupCurvePreset);
|
||||
}
|
||||
else if (result == STR_MIRROR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = -points[i];
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = 0;
|
||||
@@ -89,7 +89,7 @@ void onCurveOneMenu(const char * result)
|
||||
|
||||
void menuModelCurveOne(event_t event)
|
||||
{
|
||||
CurveData & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
|
||||
drawStringWithIndex(PSIZE(TR_MENUCURVES)*FW+FW, 0, STR_CV, s_curveChan+1);
|
||||
|
||||
@@ -52,7 +52,7 @@ void runPopupCurvePreset(event_t event)
|
||||
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
int k = 25 * reusableBuffer.curveEdit.preset;
|
||||
int dx = 2000 / (5+crv.points-1);
|
||||
@@ -73,13 +73,13 @@ void onCurveOneMenu(const char * result)
|
||||
POPUP_INPUT(STR_PRESET, runPopupCurvePreset);
|
||||
}
|
||||
else if (result == STR_MIRROR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = -points[i];
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = 0;
|
||||
@@ -92,7 +92,7 @@ void onCurveOneMenu(const char * result)
|
||||
void menuModelCurveOne(event_t event)
|
||||
{
|
||||
static uint8_t pointsOfs = 0;
|
||||
CurveData & crv = g_model.curves[s_curveChan];
|
||||
CurveHeader & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
|
||||
drawStringWithIndex(PSIZE(TR_MENUCURVES)*FW+FW, 0, "CV", s_curveChan+1);
|
||||
|
||||
@@ -22,17 +22,19 @@
|
||||
#ifndef _CURVE_H_
|
||||
#define _CURVE_H_
|
||||
|
||||
#include "form.h"
|
||||
#include "window.h"
|
||||
|
||||
struct CurvePoint {
|
||||
point_t coords;
|
||||
LcdFlags flags;
|
||||
};
|
||||
|
||||
class Curve: public FormField {
|
||||
class Curve: public Window {
|
||||
friend class CurveEdit;
|
||||
|
||||
public:
|
||||
Curve(Window * parent, const rect_t & rect, std::function<int(int)> function, std::function<int()> position=nullptr):
|
||||
FormField(parent, rect, OPAQUE),
|
||||
Window(parent, rect, OPAQUE),
|
||||
function(std::move(function)),
|
||||
position(std::move(position))
|
||||
{
|
||||
@@ -52,7 +54,7 @@ class Curve: public FormField {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
FormField::checkEvents();
|
||||
Window::checkEvents();
|
||||
}
|
||||
|
||||
void addPoint(const point_t & point, LcdFlags flags);
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include "opentx.h" // TODO for applyCustomCurve
|
||||
|
||||
CurveEdit::CurveEdit(Window * parent, const rect_t & rect, uint8_t index) :
|
||||
Curve(parent, rect, [=](int x) -> int {
|
||||
FormField(parent, rect),
|
||||
preview(this, {0, 0, width(), height()}, [=](int x) -> int {
|
||||
return applyCustomCurve(x, index);
|
||||
}),
|
||||
index(index),
|
||||
@@ -34,16 +35,16 @@ CurveEdit::CurveEdit(Window * parent, const rect_t & rect, uint8_t index) :
|
||||
|
||||
void CurveEdit::update()
|
||||
{
|
||||
clearPoints();
|
||||
CurveInfo & curve = g_model.curves[index];
|
||||
preview.clearPoints();
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
for (uint8_t i = 0; i < 5 + curve.points; i++) {
|
||||
if (hasFocus() && current == i) {
|
||||
position = [=] () -> int {
|
||||
preview.position = [=] () -> int {
|
||||
return getPoint(index, i).x;
|
||||
};
|
||||
}
|
||||
else {
|
||||
addPoint(getPoint(index, i), DEFAULT_COLOR);
|
||||
preview.addPoint(getPoint(index, i), DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
@@ -58,11 +59,11 @@ bool CurveEdit::onTouchEnd(coord_t x, coord_t y)
|
||||
|
||||
CurveKeyboard::show(this, isCustomCurve());
|
||||
|
||||
CurveInfo & curve = g_model.curves[index];
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
for (int i=0; i<5 + curve.points; i++) {
|
||||
if (i != current) {
|
||||
point_t point = getPoint(index, i);
|
||||
if (abs(getPointX(point.x) - x) <= 10 && abs(getPointY(point.y) - y) <= 10) {
|
||||
if (abs(preview.getPointX(point.x) - x) <= 10 && abs(preview.getPointY(point.y) - y) <= 10) {
|
||||
current = i;
|
||||
update();
|
||||
break;
|
||||
@@ -81,7 +82,7 @@ void CurveEdit::onFocusLost()
|
||||
|
||||
void CurveEdit::next()
|
||||
{
|
||||
if (current++ == points.size()) {
|
||||
if (current++ == preview.points.size()) {
|
||||
current = 0;
|
||||
}
|
||||
update();
|
||||
@@ -90,7 +91,7 @@ void CurveEdit::next()
|
||||
void CurveEdit::previous()
|
||||
{
|
||||
if (current-- == 0) {
|
||||
current = points.size();
|
||||
current = preview.points.size();
|
||||
}
|
||||
update();
|
||||
}
|
||||
@@ -113,7 +114,7 @@ void CurveEdit::down()
|
||||
|
||||
void CurveEdit::right()
|
||||
{
|
||||
CurveInfo & curve = g_model.curves[index];
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && current != 0 && current != curve.points + 5 - 1) {
|
||||
int8_t * points = curveAddress(index);
|
||||
int8_t * point = &points[5 + curve.points + current - 1];
|
||||
@@ -126,7 +127,7 @@ void CurveEdit::right()
|
||||
|
||||
void CurveEdit::left()
|
||||
{
|
||||
CurveInfo & curve = g_model.curves[index];
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && current != 0 && current != curve.points + 5 - 1) {
|
||||
int8_t * points = curveAddress(index);
|
||||
int8_t * point = &points[5 + curve.points + current - 1];
|
||||
|
||||
@@ -21,17 +21,13 @@
|
||||
#ifndef _CURVEEDIT_H_
|
||||
#define _CURVEEDIT_H_
|
||||
|
||||
#include "form.h"
|
||||
#include "curve.h"
|
||||
|
||||
class CurveEdit: public Curve {
|
||||
class CurveEdit: public FormField {
|
||||
public:
|
||||
CurveEdit(Window * parent, const rect_t & rect, uint8_t index);
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Curve::checkEvents();
|
||||
}
|
||||
|
||||
void update();
|
||||
|
||||
void onEvent(event_t event) override;
|
||||
@@ -43,6 +39,7 @@ class CurveEdit: public Curve {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
Curve preview;
|
||||
uint8_t index;
|
||||
uint8_t current;
|
||||
void next();
|
||||
|
||||
@@ -24,18 +24,6 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
bool isCurveFilled(uint8_t index)
|
||||
{
|
||||
CurveInfo &curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
for (int i = 0; i < 5 + curve.points; i++) {
|
||||
if (points[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class CurveEditWindow : public Page {
|
||||
public:
|
||||
explicit CurveEditWindow(uint8_t index):
|
||||
@@ -52,12 +40,91 @@ class CurveEditWindow : public Page {
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, {70, 4, LCD_W - 100, 20}, STR_MENUCURVE, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUCURVE, MENU_TITLE_COLOR);
|
||||
char s[16];
|
||||
strAppendStringWithIndex(s, STR_CV, index + 1);
|
||||
new StaticText(window, {70, 28, LCD_W - 100, 20}, s, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, s, MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
#if LCD_W > LCD_H
|
||||
void buildBody(Window * window)
|
||||
{
|
||||
coord_t curveWidth = window->height() - 2 * PAGE_PADDING;
|
||||
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
// Curve editor
|
||||
curveEdit = new CurveEdit(window, { LCD_W - curveWidth - PAGE_PADDING, PAGE_PADDING, curveWidth, curveWidth}, index);
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setLabelWidth(PAGE_PADDING);
|
||||
grid.setMarginRight(curveWidth + 2 * PAGE_PADDING);
|
||||
grid.spacer(PAGE_PADDING);
|
||||
|
||||
// Name
|
||||
new StaticText(window, grid.getFieldSlot(), STR_NAME);
|
||||
grid.nextLine();
|
||||
new TextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name));
|
||||
grid.nextLine();
|
||||
|
||||
// Type
|
||||
new StaticText(window, grid.getFieldSlot(), STR_TYPE);
|
||||
grid.nextLine();
|
||||
new Choice(window, grid.getFieldSlot(2, 0), STR_CURVE_TYPES, 0, 1, GET_DEFAULT(g_model.curves[index].type),
|
||||
[=](int32_t newValue) {
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
if (newValue != curve.type) {
|
||||
for (int i = 1; i < 4 + curve.points; i++) {
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + curve.points)), index));
|
||||
}
|
||||
if (moveCurve(index, newValue == CURVE_TYPE_CUSTOM ? 3 + curve.points : -3 - curve.points)) {
|
||||
if (newValue == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
curve.type = newValue;
|
||||
}
|
||||
SET_DIRTY();
|
||||
curveEdit->update();
|
||||
}
|
||||
});
|
||||
|
||||
// Points count
|
||||
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 1), 2, 17, GET_DEFAULT(g_model.curves[index].points + 5),
|
||||
[=](int32_t newValue) {
|
||||
newValue -= 5;
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int newPoints[MAX_POINTS_PER_CURVE];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4 + newValue] = points[4 + curve.points];
|
||||
for (int i = 1; i < 4 + newValue; i++)
|
||||
newPoints[i] = calcRESXto100(applyCustomCurve(-RESX + (i * 2 * RESX) / (4 + newValue), index));
|
||||
if (moveCurve(index, (newValue - curve.points) * (curve.type == CURVE_TYPE_CUSTOM ? 2 : 1))) {
|
||||
for (int i = 0; i < 5 + newValue; i++) {
|
||||
points[i] = newPoints[i];
|
||||
if (curve.type == CURVE_TYPE_CUSTOM && i != 0 && i != 4 + newValue)
|
||||
points[5 + newValue + i - 1] = -100 + (i * 200) / (4 + newValue);
|
||||
}
|
||||
curve.points = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->update();
|
||||
}
|
||||
});
|
||||
edit->setSuffix(STR_PTS);
|
||||
grid.nextLine();
|
||||
|
||||
// Smooth
|
||||
new StaticText(window, grid.getFieldSlot(), STR_SMOOTH);
|
||||
grid.nextLine();
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_DEFAULT(g_model.curves[index].smooth),
|
||||
[=](int32_t newValue) {
|
||||
g_model.curves[index].smooth = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->update();
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
#else
|
||||
void buildBody(Window * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
@@ -66,7 +133,7 @@ class CurveEditWindow : public Page {
|
||||
grid.setLabelWidth(100);
|
||||
grid.spacer(20);
|
||||
|
||||
CurveInfo & curve = g_model.curves[index];
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
// Curve editor
|
||||
@@ -82,7 +149,7 @@ class CurveEditWindow : public Page {
|
||||
new StaticText(window, grid.getLabelSlot(), STR_TYPE);
|
||||
new Choice(window, grid.getFieldSlot(2, 0), STR_CURVE_TYPES, 0, 1, GET_DEFAULT(g_model.curves[index].type),
|
||||
[=](int32_t newValue) {
|
||||
CurveInfo &curve = g_model.curves[index];
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
if (newValue != curve.type) {
|
||||
for (int i = 1; i < 4 + curve.points; i++) {
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i * 200 / (4 + curve.points)), index));
|
||||
@@ -102,7 +169,7 @@ class CurveEditWindow : public Page {
|
||||
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 1), 2, 17, GET_DEFAULT(g_model.curves[index].points + 5),
|
||||
[=](int32_t newValue) {
|
||||
newValue -= 5;
|
||||
CurveInfo &curve = g_model.curves[index];
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int newPoints[MAX_POINTS_PER_CURVE];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4 + newValue] = points[4 + curve.points];
|
||||
@@ -131,8 +198,8 @@ class CurveEditWindow : public Page {
|
||||
curveEdit->update();
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CurveButton : public Button {
|
||||
@@ -141,7 +208,7 @@ class CurveButton : public Button {
|
||||
Button(parent, rect),
|
||||
index(index)
|
||||
{
|
||||
if (isCurveFilled(index)) {
|
||||
if (isCurveUsed(index)) {
|
||||
setHeight(130);
|
||||
new Curve(this, {5, 5, 120, 120},
|
||||
[=](int x) -> int {
|
||||
@@ -156,12 +223,12 @@ class CurveButton : public Button {
|
||||
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
|
||||
|
||||
// curve characteristics
|
||||
if (isCurveFilled(index)) {
|
||||
CurveInfo &curve = g_model.curves[index];
|
||||
if (isCurveUsed(index)) {
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
dc->drawNumber(130, 5, 5 + curve.points, LEFT, 0, nullptr, STR_PTS);
|
||||
dc->drawTextAtIndex(130, 25, STR_CURVE_TYPES, curve.type);
|
||||
if (curve.smooth)
|
||||
dc->drawText(130, 45, "Smooth");
|
||||
dc->drawText(130, 45, STR_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,66 +264,68 @@ void ModelCurvesPage::build(FormWindow * window, int8_t focusIndex)
|
||||
grid.setLabelWidth(66);
|
||||
|
||||
for (uint8_t index = 0; index < MAX_CURVES; index++) {
|
||||
CurveInfo &curve = g_model.curves[index];
|
||||
CurveHeader &curve = g_model.curves[index];
|
||||
int8_t * points = curveAddress(index);
|
||||
|
||||
// Curve label
|
||||
new StaticText(window, grid.getLabelSlot(), getCurveString(1 + index), BUTTON_BACKGROUND | CENTERED);
|
||||
if (isCurveUsed(index)) {
|
||||
// Curve label
|
||||
new StaticText(window, grid.getLabelSlot(), getCurveString(1 + index), BUTTON_BACKGROUND | CENTERED);
|
||||
|
||||
// Curve drawing
|
||||
Button * button = new CurveButton(window, grid.getFieldSlot(), index);
|
||||
button->setPressHandler([=]() -> uint8_t {
|
||||
Menu * menu = new Menu();
|
||||
menu->addLine(STR_EDIT, [=]() {
|
||||
editCurve(window, index);
|
||||
});
|
||||
menu->addLine(STR_CURVE_PRESET, [=]() {
|
||||
Menu * menu = new Menu();
|
||||
for (int angle = -45; angle <= 45; angle += 15) {
|
||||
char label[16];
|
||||
strAppend(strAppendSigned(label, angle), "@");
|
||||
menu->addLine(label, [=]() {
|
||||
int dx = 2000 / (5 + curve.points - 1);
|
||||
for (uint8_t i = 0; i < 5 + curve.points; i++) {
|
||||
int x = -1000 + i * dx;
|
||||
points[i] = div_and_round(angle * x, 450);
|
||||
}
|
||||
if (curve.type == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, index);
|
||||
// Curve drawing
|
||||
Button * button = new CurveButton(window, grid.getFieldSlot(), index);
|
||||
button->setPressHandler([=]() -> uint8_t {
|
||||
Menu * menu = new Menu();
|
||||
menu->addLine(STR_EDIT, [=]() {
|
||||
editCurve(window, index);
|
||||
});
|
||||
}
|
||||
menu->addLine(STR_CURVE_PRESET, [=]() {
|
||||
Menu * menu = new Menu();
|
||||
for (int angle = -45; angle <= 45; angle += 15) {
|
||||
char label[16];
|
||||
strAppend(strAppendSigned(label, angle), "@");
|
||||
menu->addLine(label, [=]() {
|
||||
int dx = 2000 / (5 + curve.points - 1);
|
||||
for (uint8_t i = 0; i < 5 + curve.points; i++) {
|
||||
int x = -1000 + i * dx;
|
||||
points[i] = div_and_round(angle * x, 450);
|
||||
}
|
||||
if (curve.type == CURVE_TYPE_CUSTOM) {
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
}
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, index);
|
||||
});
|
||||
}
|
||||
});
|
||||
menu->addLine(STR_MIRROR, [=]() {
|
||||
curveMirror(index);
|
||||
storageDirty(EE_MODEL);
|
||||
button->invalidate();
|
||||
});
|
||||
menu->addLine(STR_CLEAR, [=]() {
|
||||
curveReset(index);
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, index);
|
||||
});
|
||||
return 0;
|
||||
});
|
||||
if (isCurveFilled(index)) {
|
||||
menu->addLine(STR_MIRROR, [=]() {
|
||||
for (int i = 0; i < 5 + curve.points; i++)
|
||||
points[i] = -points[i];
|
||||
storageDirty(EE_MODEL);
|
||||
button->invalidate();
|
||||
});
|
||||
menu->addLine(STR_CLEAR, [=]() {
|
||||
for (int i = 0; i < 5 + curve.points; i++)
|
||||
points[i] = 0;
|
||||
if (curve.type == CURVE_TYPE_CUSTOM)
|
||||
resetCustomCurveX(points, 5 + curve.points);
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, index);
|
||||
});
|
||||
|
||||
if (focusIndex == index) {
|
||||
button->setFocus();
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (focusIndex == index) {
|
||||
button->setFocus();
|
||||
grid.spacer(button->height() + 5);
|
||||
}
|
||||
else {
|
||||
auto button = new TextButton(window, grid.getLabelSlot(), getCurveString(1 + index));
|
||||
button->setPressHandler([=]() {
|
||||
editCurve(window, index);
|
||||
return 0;
|
||||
});
|
||||
grid.spacer(button->height() + 5);
|
||||
}
|
||||
|
||||
grid.spacer(button->height() + 5);
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
window->setLastField();
|
||||
window->setInnerHeight(grid.getWindowHeight());
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ class InputEditWindow: public Page {
|
||||
Choice * curveTypeChoice = nullptr;
|
||||
|
||||
void buildHeader(Window * window) {
|
||||
new StaticText(window, { 50, 0, 100, 20 }, STR_MENUINPUTS, MENU_TITLE_COLOR);
|
||||
new StaticText(window, { 50, FH+2, 100, 20 }, getSourceString(MIXSRC_FIRST_INPUT + input), MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUINPUTS, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_FIRST_INPUT + input), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
void updateCurves() {
|
||||
|
||||
@@ -58,6 +58,8 @@ class LogicalSwitchEditWindow: public Page {
|
||||
headerSwitchName->setFlags(isActive() ? BOLD|WARNING_COLOR : MENU_TITLE_COLOR);
|
||||
active = !active;
|
||||
}
|
||||
|
||||
Page::checkEvents();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -183,8 +185,8 @@ class LogicalSwitchEditWindow: public Page {
|
||||
}
|
||||
|
||||
void buildHeader(Window * window) {
|
||||
new StaticText(window, { 70, 4, LCD_W - 100, 20 }, STR_MENULOGICALSWITCHES, MENU_TITLE_COLOR);
|
||||
headerSwitchName = new StaticText(window, { 70, 28, LCD_W - 100, 20 }, getSwitchPositionName(SWSRC_SW1+ls), MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENULOGICALSWITCHES, MENU_TITLE_COLOR);
|
||||
headerSwitchName = new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSwitchPositionName(SWSRC_SW1+ls), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
void buildBody(Window * window) {
|
||||
@@ -256,7 +258,7 @@ class LogicalSwitchButton : public Button {
|
||||
Button::checkEvents();
|
||||
}
|
||||
|
||||
virtual void paint(BitmapBuffer * dc) override
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
LogicalSwitchData * ls = lswAddress(lsIndex);
|
||||
uint8_t lsFamily = lswFamily(ls->func);
|
||||
@@ -341,15 +343,19 @@ void ModelLogicalSwitchesPage::build(FormWindow * window, int8_t focusIndex)
|
||||
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++) {
|
||||
LogicalSwitchData * ls = lswAddress(i);
|
||||
if (ls->func == LS_FUNC_NONE) {
|
||||
auto label = new TextButton(window, grid.getLabelSlot(), getSwitchPositionName(SWSRC_SW1+i));
|
||||
grid.spacer(label->height() + 5);
|
||||
auto button = new TextButton(window, grid.getLabelSlot(), getSwitchPositionName(SWSRC_SW1+i));
|
||||
button->setPressHandler([=]() {
|
||||
editLogicalSwitch(window, i);
|
||||
return 0;
|
||||
});
|
||||
grid.spacer(button->height() + 5);
|
||||
}
|
||||
else {
|
||||
new StaticText(window, grid.getLabelSlot(), getSwitchPositionName(SWSRC_SW1 + i), BUTTON_BACKGROUND | CENTERED);
|
||||
Button * button = new LogicalSwitchButton(window, grid.getFieldSlot(), i,
|
||||
[=]() -> uint8_t {
|
||||
Menu *menu = new Menu();
|
||||
LogicalSwitchData *ls = lswAddress(i);
|
||||
[=]() {
|
||||
Menu * menu = new Menu();
|
||||
LogicalSwitchData * ls = lswAddress(i);
|
||||
menu->addLine(STR_EDIT, [=]() {
|
||||
editLogicalSwitch(window, i);
|
||||
});
|
||||
|
||||
@@ -72,8 +72,8 @@ class MixEditWindow : public Page {
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, {70, 4, 100, 20}, STR_MIXER, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {70, 28, 100, 20}, getSourceString(MIXSRC_CH1 + channel), MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MIXER, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_CH1 + channel), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
void updateCurves()
|
||||
|
||||
@@ -39,8 +39,8 @@ class OutputEditWindow : public Page {
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, {70, 4, 100, 20}, STR_MENULIMITS, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {70, 28, 100, 20}, getSourceString(MIXSRC_CH1 + channel), MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENULIMITS, MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_CH1 + channel), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
void buildBody(Window * window)
|
||||
|
||||
@@ -125,7 +125,7 @@ class SensorEditWindow : public Page {
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, {70, 4, 200, 20}, STR_SENSOR + std::to_string(index + 1), MENU_TITLE_COLOR);
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_SENSOR + std::to_string(index + 1), MENU_TITLE_COLOR);
|
||||
// dynamic display of sensor value ?
|
||||
//new StaticText(window, {70, 28, 100, 20}, "SF" + std::to_string(index), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ class SpecialFunctionEditPage : public Page {
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, { 60, 2, 200, 20 }, functions == g_model.customFn ? STR_MENUCUSTOMFUNC : STR_MENUSPECIALFUNCS, MENU_TITLE_COLOR);
|
||||
headerSF = new StaticText(window, { 60, 22, 100, 20 }, (functions == g_model.customFn ? "SF" : "GF" ) + std::to_string(index), MENU_TITLE_COLOR);
|
||||
new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, 20 }, functions == g_model.customFn ? STR_MENUCUSTOMFUNC : STR_MENUSPECIALFUNCS, MENU_TITLE_COLOR);
|
||||
headerSF = new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, 20 }, (functions == g_model.customFn ? "SF" : "GF" ) + std::to_string(index), MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
void updateSpecialFunctionOneWindow(FormField * previousField, FormField * nextField)
|
||||
|
||||
@@ -83,7 +83,7 @@ void menuModelCurvesAll(event_t event)
|
||||
#endif
|
||||
{
|
||||
drawStringWithIndex(0, y, STR_CV, k+1, attr);
|
||||
CurveData & crv = g_model.curves[k];
|
||||
CurveHeader & crv = g_model.curves[k];
|
||||
editName(4*FW, y, crv.name, sizeof(crv.name), 0, 0);
|
||||
#if LCD_W >= 212
|
||||
lcdDrawNumber(11*FW, y, 5+crv.points, LEFT);
|
||||
|
||||
+30
-30
@@ -829,33 +829,33 @@ static int luaModelGetCurve(lua_State *L)
|
||||
{
|
||||
unsigned int idx = luaL_checkunsigned(L, 1);
|
||||
if (idx < MAX_CURVES) {
|
||||
CurveData & curveData = g_model.curves[idx];
|
||||
CurveHeader & CurveHeader = g_model.curves[idx];
|
||||
lua_newtable(L);
|
||||
lua_pushtablezstring(L, "name", curveData.name);
|
||||
lua_pushtableinteger(L, "type", curveData.type);
|
||||
lua_pushtableboolean(L, "smooth", curveData.smooth);
|
||||
lua_pushtableinteger(L, "points", curveData.points + 5);
|
||||
lua_pushtablezstring(L, "name", CurveHeader.name);
|
||||
lua_pushtableinteger(L, "type", CurveHeader.type);
|
||||
lua_pushtableboolean(L, "smooth", CurveHeader.smooth);
|
||||
lua_pushtableinteger(L, "points", CurveHeader.points + 5);
|
||||
lua_pushstring(L, "y");
|
||||
lua_newtable(L);
|
||||
int8_t * point = curveAddress(idx);
|
||||
for (int i=0; i < curveData.points + 5; i++) {
|
||||
for (int i=0; i < CurveHeader.points + 5; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushinteger(L, *point++);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
if (curveData.type == CURVE_TYPE_CUSTOM) {
|
||||
if (CurveHeader.type == CURVE_TYPE_CUSTOM) {
|
||||
lua_pushstring(L, "x");
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, 0);
|
||||
lua_pushinteger(L, -100);
|
||||
lua_settable(L, -3);
|
||||
for (int i=0; i < curveData.points + 3; i++) {
|
||||
for (int i=0; i < CurveHeader.points + 3; i++) {
|
||||
lua_pushinteger(L, i+1);
|
||||
lua_pushinteger(L, *point++);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_pushinteger(L, curveData.points + 4);
|
||||
lua_pushinteger(L, CurveHeader.points + 4);
|
||||
lua_pushinteger(L, 100);
|
||||
lua_settable(L, -3);
|
||||
lua_settable(L, -3);
|
||||
@@ -922,9 +922,9 @@ static int luaModelSetCurve(lua_State *L)
|
||||
memset(yPoints, -127, sizeof(yPoints));
|
||||
|
||||
|
||||
CurveData &destCurveData = g_model.curves[curveIdx];
|
||||
CurveData newCurveData;
|
||||
memclear(&newCurveData, sizeof(CurveData));
|
||||
CurveHeader &destCurveHeader = g_model.curves[curveIdx];
|
||||
CurveHeader newCurveHeader;
|
||||
memclear(&newCurveHeader, sizeof(CurveHeader));
|
||||
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||
@@ -932,18 +932,18 @@ static int luaModelSetCurve(lua_State *L)
|
||||
const char *key = luaL_checkstring(L, -2);
|
||||
if (!strcmp(key, "name")) {
|
||||
const char *name = luaL_checkstring(L, -1);
|
||||
str2zchar(newCurveData.name, name, sizeof(newCurveData.name));
|
||||
str2zchar(newCurveHeader.name, name, sizeof(newCurveHeader.name));
|
||||
}
|
||||
else if (!strcmp(key, "type")) {
|
||||
newCurveData.type = luaL_checkinteger(L, -1);
|
||||
newCurveHeader.type = luaL_checkinteger(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "smooth")) {
|
||||
// Earlier version of this api expected a 0/1 integer instead of a boolean
|
||||
// Still accept a 0/1 here
|
||||
if (lua_isboolean(L,-1))
|
||||
newCurveData.smooth = lua_toboolean(L, -1);
|
||||
newCurveHeader.smooth = lua_toboolean(L, -1);
|
||||
else
|
||||
newCurveData.smooth = luaL_checkinteger(L, -1);
|
||||
newCurveHeader.smooth = luaL_checkinteger(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "x") || !strcmp(key, "y")) {
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
@@ -972,14 +972,14 @@ static int luaModelSetCurve(lua_State *L)
|
||||
do {
|
||||
numPoints++;
|
||||
} while (yPoints[numPoints]!=-127 && numPoints < MAX_POINTS_PER_CURVE);
|
||||
newCurveData.points = numPoints - 5;
|
||||
newCurveHeader.points = numPoints - 5;
|
||||
|
||||
if (numPoints < MIN_POINTS_PER_CURVE || numPoints > MAX_POINTS_PER_CURVE) {
|
||||
lua_pushinteger(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (newCurveData.type == CURVE_TYPE_CUSTOM) {
|
||||
if (newCurveHeader.type == CURVE_TYPE_CUSTOM) {
|
||||
|
||||
// The rest of the points are checked by the monotonic condition
|
||||
for (unsigned int i=numPoints; i < sizeof(xPoints);i++)
|
||||
@@ -992,7 +992,7 @@ static int luaModelSetCurve(lua_State *L)
|
||||
}
|
||||
|
||||
// Check first and last point
|
||||
if (xPoints[0] != -100 || xPoints[newCurveData.points + 4] != 100) {
|
||||
if (xPoints[0] != -100 || xPoints[newCurveHeader.points + 4] != 100) {
|
||||
lua_pushinteger(L, 5);
|
||||
return 1;
|
||||
}
|
||||
@@ -1007,7 +1007,7 @@ static int luaModelSetCurve(lua_State *L)
|
||||
}
|
||||
|
||||
// Check that ypoints have the right number of points set
|
||||
for (int i=0; i < 5 + newCurveData.points;i++)
|
||||
for (int i=0; i < 5 + newCurveHeader.points;i++)
|
||||
{
|
||||
if (yPoints[i] == -127)
|
||||
{
|
||||
@@ -1018,19 +1018,19 @@ static int luaModelSetCurve(lua_State *L)
|
||||
|
||||
// Calculate size of curve we replace
|
||||
int oldCurveMemSize;
|
||||
if (destCurveData.type == CURVE_TYPE_STANDARD) {
|
||||
oldCurveMemSize = 5 + destCurveData.points;
|
||||
if (destCurveHeader.type == CURVE_TYPE_STANDARD) {
|
||||
oldCurveMemSize = 5 + destCurveHeader.points;
|
||||
}
|
||||
else {
|
||||
oldCurveMemSize = 8 + 2 * destCurveData.points;
|
||||
oldCurveMemSize = 8 + 2 * destCurveHeader.points;
|
||||
}
|
||||
|
||||
// Calculate own size
|
||||
int newCurveMemSize;
|
||||
if (newCurveData.type == CURVE_TYPE_STANDARD)
|
||||
newCurveMemSize = 5 + newCurveData.points;
|
||||
if (newCurveHeader.type == CURVE_TYPE_STANDARD)
|
||||
newCurveMemSize = 5 + newCurveHeader.points;
|
||||
else
|
||||
newCurveMemSize = 8 + 2 * newCurveData.points;
|
||||
newCurveMemSize = 8 + 2 * newCurveHeader.points;
|
||||
|
||||
int shift = newCurveMemSize - oldCurveMemSize;
|
||||
|
||||
@@ -1042,15 +1042,15 @@ static int luaModelSetCurve(lua_State *L)
|
||||
}
|
||||
|
||||
// Curve fits into mem, fill new curve
|
||||
destCurveData = newCurveData;
|
||||
destCurveHeader = newCurveHeader;
|
||||
|
||||
int8_t *point = curveAddress(curveIdx);
|
||||
for (int i = 0; i < destCurveData.points + 5; i++) {
|
||||
for (int i = 0; i < destCurveHeader.points + 5; i++) {
|
||||
*point++ = yPoints[i];
|
||||
}
|
||||
|
||||
if (destCurveData.type == CURVE_TYPE_CUSTOM) {
|
||||
for (int i = 1; i < destCurveData.points + 4; i++) {
|
||||
if (destCurveHeader.type == CURVE_TYPE_CUSTOM) {
|
||||
for (int i = 1; i < destCurveHeader.points + 4; i++) {
|
||||
*point++ = xPoints[i];
|
||||
}
|
||||
}
|
||||
|
||||
+2
-24
@@ -256,6 +256,7 @@
|
||||
#endif
|
||||
|
||||
#include "myeeprom.h"
|
||||
#include "curves.h"
|
||||
|
||||
inline void memclear(void * p, size_t size)
|
||||
{
|
||||
@@ -802,31 +803,8 @@ inline void getGVarIncDecRange(int16_t & valMin, int16_t & valMax)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Curves
|
||||
enum BaseCurves {
|
||||
CURVE_NONE,
|
||||
CURVE_X_GT0,
|
||||
CURVE_X_LT0,
|
||||
CURVE_ABS_X,
|
||||
CURVE_F_GT0,
|
||||
CURVE_F_LT0,
|
||||
CURVE_ABS_F,
|
||||
CURVE_BASE
|
||||
};
|
||||
int8_t * curveAddress(uint8_t idx);
|
||||
|
||||
point_t getPoint(uint8_t i);
|
||||
point_t getPoint(uint8_t curveIndex, uint8_t index);
|
||||
typedef CurveData CurveInfo;
|
||||
void loadCurves();
|
||||
#define LOAD_MODEL_CURVES() loadCurves()
|
||||
int intpol(int x, uint8_t idx);
|
||||
int applyCurve(int x, CurveRef & curve);
|
||||
int applyCustomCurve(int x, uint8_t idx);
|
||||
int applyCurrentCurve(int x);
|
||||
int8_t getCurveX(int noPoints, int point);
|
||||
void resetCustomCurveX(int8_t * points, int noPoints);
|
||||
bool moveCurve(uint8_t index, int8_t shift); // TODO bool?
|
||||
|
||||
|
||||
void clearInputs();
|
||||
void defaultInputs();
|
||||
|
||||
@@ -200,7 +200,7 @@ PACK(typedef struct {
|
||||
uint8_t smooth:1;
|
||||
uint8_t spare:4;
|
||||
int8_t points;
|
||||
}) CurveData_v216;
|
||||
}) CurveHeader_v216;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
PACK(typedef struct {
|
||||
@@ -586,7 +586,7 @@ PACK(typedef struct {
|
||||
LimitData_v216 limitData[MAX_OUTPUT_CHANNELS_218];
|
||||
ExpoData_v216 expoData[MAX_EXPOS_218];
|
||||
|
||||
CurveData_v216 curves[MAX_CURVES_218];
|
||||
CurveHeader_v216 curves[MAX_CURVES_218];
|
||||
int8_t points[MAX_CURVE_POINTS_218];
|
||||
|
||||
LogicalSwitchData_v216 logicalSw[32];
|
||||
@@ -632,7 +632,7 @@ PACK(typedef struct {
|
||||
LimitData limitData[MAX_OUTPUT_CHANNELS_218];
|
||||
ExpoData_v217 expoData[MAX_EXPOS_218];
|
||||
|
||||
CurveData_v216 curves[MAX_CURVES_218];
|
||||
CurveHeader_v216 curves[MAX_CURVES_218];
|
||||
int8_t points[MAX_CURVE_POINTS_218];
|
||||
|
||||
LogicalSwitchData_v217 logicalSw[MAX_LOGICAL_SWITCHES_218];
|
||||
|
||||
@@ -164,7 +164,7 @@ void convertModelData_218_to_219(ModelData &model)
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<MAX_CURVES_218; i++) {
|
||||
memmove(&newModel.curves[i], &oldModel.curves[i], sizeof(CurveData_v218));
|
||||
memmove(&newModel.curves[i], &oldModel.curves[i], sizeof(CurveHeader_v218));
|
||||
}
|
||||
|
||||
for (uint32_t i=0; i<MAX_CURVE_POINTS_218; i++) {
|
||||
|
||||
@@ -249,7 +249,7 @@ PACK(typedef struct {
|
||||
uint8_t smooth:1;
|
||||
int8_t points:6; // describes number of points - 5
|
||||
char name[LEN_CURVE_NAME_218];
|
||||
}) CurveData_v218;
|
||||
}) CurveHeader_v218;
|
||||
|
||||
PACK(typedef struct {
|
||||
int16_t calib[4];
|
||||
@@ -447,7 +447,7 @@ PACK(struct ModelData_v218 {
|
||||
LimitData limitData[MAX_OUTPUT_CHANNELS_218];
|
||||
ExpoData_v218 expoData[MAX_EXPOS_218];
|
||||
|
||||
CurveData_v218 curves[MAX_CURVES_218];
|
||||
CurveHeader_v218 curves[MAX_CURVES_218];
|
||||
int8_t points[MAX_CURVE_POINTS_218];
|
||||
|
||||
LogicalSwitchData_v218 logicalSw[MAX_LOGICAL_SWITCHES_218];
|
||||
|
||||
@@ -102,7 +102,7 @@ void copyFlightModeData(A * dest, B * src)
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
void copyCurveData(A * dest, B * src)
|
||||
void copyCurveHeader(A * dest, B * src)
|
||||
{
|
||||
dest->type = src->type;
|
||||
dest->smooth = src->smooth;
|
||||
@@ -259,7 +259,7 @@ void copyModelData(A * dest, B * src)
|
||||
copyExpoData(&dest->expoData[i], &src->expoData[i]);
|
||||
}
|
||||
for (int i=0; i<32; i++) {
|
||||
copyCurveData(&dest->curves[i], &src->curves[i]);
|
||||
copyCurveHeader(&dest->curves[i], &src->curves[i]);
|
||||
}
|
||||
memcpy(dest->points, src->points, sizeof(dest->points));
|
||||
for (int i=0; i<64; i++) {
|
||||
|
||||
@@ -157,7 +157,7 @@ void postModelLoad(bool alarms)
|
||||
}
|
||||
}
|
||||
|
||||
LOAD_MODEL_CURVES();
|
||||
loadCurves();
|
||||
|
||||
resumeMixerCalculations();
|
||||
if (pulsesStarted()) {
|
||||
|
||||
@@ -88,6 +88,9 @@ constexpr uint32_t ALERT_MESSAGE_TOP = ALERT_TITLE_TOP + 90;
|
||||
constexpr uint32_t ALERT_MESSAGE_LEFT = ALERT_TITLE_LEFT;
|
||||
constexpr uint32_t ALERT_ACTION_TOP = 240;
|
||||
|
||||
constexpr uint32_t PAGE_TITLE_TOP = 2;
|
||||
constexpr uint32_t PAGE_TITLE_LEFT = 50;
|
||||
|
||||
// TODO common code, not in target
|
||||
enum LcdColorIndex
|
||||
{
|
||||
|
||||
@@ -87,6 +87,9 @@ constexpr uint32_t ALERT_MESSAGE_LEFT = ALERT_TITLE_LEFT;
|
||||
constexpr uint32_t ALERT_ACTION_TOP = 240;
|
||||
constexpr uint32_t ALERT_BUTTON_TOP = 300;
|
||||
|
||||
constexpr uint32_t PAGE_TITLE_TOP = 4;
|
||||
constexpr uint32_t PAGE_TITLE_LEFT = 70;
|
||||
|
||||
enum LcdColorIndex
|
||||
{
|
||||
DEFAULT_COLOR_INDEX,
|
||||
|
||||
Vendored
+1
-1
Submodule radio/src/thirdparty/libopenui updated: 9807aaec0d...50eb0980b3
Reference in New Issue
Block a user