Merge pull request #4 from opentx/2.3

Merge from Original
This commit is contained in:
richardclli
2021-04-19 15:03:12 +08:00
committed by GitHub
552 changed files with 48684 additions and 16403 deletions
+1
View File
@@ -7,6 +7,7 @@
<option name="FUNCTION_BRACE_PLACEMENT" value="2" />
<option name="SUPERCLASS_LIST_BEFORE_COLON" value="0" />
<option name="SPACE_AFTER_POINTER_IN_DECLARATION" value="true" />
<option name="SPACE_AFTER_REFERENCE_IN_DECLARATION" value="true" />
</Objective-C>
<codeStyleSettings language="CMake">
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
-1
View File
@@ -1,6 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
+4
View File
@@ -16,6 +16,8 @@ addons:
- libmpc3
- libfox-1.6-dev
- libgtest-dev
- lib32stdc++6
- libclang-common-6.0-dev
- clang-6.0
- python3-pip
@@ -44,6 +46,8 @@ before_install:
- sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size
- sudo apt-get install --yes --force-yes -qq qt${QT_BASE}base qt${QT_BASE}multimedia qt${QT_BASE}svg qt${QT_BASE}tools; source /opt/qt${QT_BASE}/bin/qt${QT_BASE}-env.sh
- sudo ln -sf /usr/bin/python3 /usr/bin/python
- python3 -m pip install pip==20.3.3
- sudo apt-get install python3-setuptools
- python3 -m pip install pillow clang
script:
+2 -2
View File
@@ -2,11 +2,11 @@ project(OpenTX)
set(VERSION_MAJOR "2")
set(VERSION_MINOR "3")
set(VERSION_REVISION "10")
set(VERSION_REVISION "12")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
set(SDCARD_REVISION "0029")
set(SDCARD_REVISION "0036")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8)
+400
View File
@@ -1,6 +1,7 @@
[Main developers]
Bertrand Songis (bsongis)
André Bernet (kilrah)
JC D. (3djc)
Michael Blandford
Damjan Adamic (projectkk2glider)
Franck Aguerre (jivarofad)
@@ -9,6 +10,7 @@ Martin Hotař (mhotar)
Maxim (Max) Paperno (mpaperno)
Arne Schwabe (schwabe)
Daniel Gorbea (dgatf)
Neil Horne (elecpower)
[Translators]
[fr] Sebastien Charpentier (LapinFou)
@@ -32,6 +34,7 @@ Michael Byrne
<a href="https://www.flysky-cn.com/home">FlySky (monthly)</a>
<a href="https://www.jumper-rc.com">JumperRC (monthly)</a>
<a href="https://www.radiomasterrc.com">RadioMaster (monthly)</a>
<a href="http://www.happymodel.cn">HappyModel (monthly)</a>
<a href="https://alofthobbies.com">Aloft Hobbies</a>
<a href="https://jonathan.it">Jonathan Modellismo</a>
<a href="http://wstech.de">WsTech</a>
@@ -1838,3 +1841,400 @@ Laurence Gerrard
Nico Wagner
Christoph Rössner
Ruben Flores
Jim Cukla
Lee Taylor
Stefan Kuster
Barry Wright
Steven Gilley
Lloyd Evans
Nolan O'Hearne
Jeffrey James N Buffie
James Houck
Andreas Arlt
William Walker
Salvador Munoz Vinas
Chris Geiger Photography
John F Smith
Robert Zecha
Fernando Martins
Martin Brungard
Paul Witko
Michael Campbell
Stuart Posnett
PK Doddema
Leonard MacKey
Andrew Peterson
Dominik Sedlacek
Ronald Hellstern
Vicente Suarez
Patrick Geerts
Rossi Giampaolo
Jose Luis Franco Torres
Bart Sillen
Antonio Moreno
Carolina Carcione
Lonnie Misner
John Eppling
Phillip Elliott
Robin Bayer
Jurij Peternel
George Aandahl
Guy Dangerfield
Thomas Limpert
Ismael G Zapater
Alan Hall
Bradley Goodwin
Paul Dittman
John Johnson
Liam Mahoney
Joseph Carr
Fiorenzo Agnelli
Brian Ramsey
Angelo Movio
Weldon Parks
Simon Brink
Weldon Parks
Ralf Herzenbruch
Ashley Pearce
SneakIT
Soaring Stuff
Jörg Lemnitz
Johann Gross
Mark Gibson
Rendall Assoc
Cozyn Holdings Pty Ltd
Tim Karsten
Nick Hesson
Laurent Lapassade
Peter Deacon
Gilles Dando
Philippe Desrichard
Jón Haase
Michael Hansen
Sylvain Vanston
Helmut Nemecek
Alexander Mathis
Jay Watkins
Patrice Oudjaoudi
Didier Hochedez
Robert Hunter
Christophe Gilsoul
Lincoln Roberts
Johan Jurriens
Michael Ledward
Dave Waldesbuehl
Dale Rhoads
Denis Kelly
SBEurope LTD
Jean-Louis Mouche
Grant Mills
Fernando Rimoldi
Jim Cukla
Tomas Kirnak
Raymond Henderson
James Jewitt
Martin Sauter
Philip Hawkey
Lonnie Misner
Michael Hirschauer
Brian Bracken
Stuart Olson
Terry McKinley
Miklos Turcsin
Edward Skerness
Stefano Perinetti
Toni Marchante
Stuart Olson
Peter Campbell
Keith Wood
Leo Duflou
Michael Florey
Gerhard Weixelbaumer
Peter K Lehotsky
Elisha Jones
Joerg Sattler
paul42
Pascal Heg
Bjorn Sorenssen
Chris Payne
Pascal Afflard
Robert Boboryko
Chris Whitehead
David Bradley
Ian Lever
Phillip Barber
Jan Bronee
N Haasnoot
Rick Smith
Randall Grant
Patrick Degouy
Piotr Zdanowski
David Gardner
TMac FPV
Bernard Thompson
Mark Sutton
Darren J Crane
Michael Keyes
Magnus Borg
David Lorentzen
Antony Smith
Aleksandr Sarkisov
Johannes Kuhne
Kathleen Cilluffo
David Hoffmann
Alan Porter
Arlé Mooldijk
Tenbones
Kim Bitsch Lauridsen
Arthur Costerus
Peter Harvey
John Simpson
Landy de los Santos
Graham Ridley
Schenk Peter
Joseph Rex
Richard Honeywell
Roy Nixon
Andrew Shewan
David Bradley
Alan Micklethwaite
Susan Siegel
Stephen Evans
William Hallman
Franck Michel
László Gajcsi (monthly)
Danny Koch
Robert Martin
Gavin Meerwald
Frédéric Maix
Frank Steinberg
Kevin Berkefeld
Marccos Colon
Kerry Reynolds
Kim Jeppesen
Arthur Peters
Andrew Lowes
Anthony Hallo
Bill Hill
Gerard Falaise
Kevin Raynor
Lorenzo gh
Jan Landeweer
David Bland
Manuel Spoerri
Jeff Jacobs
David Thorne
Maddox Philip
James Jewitt
Justin Digby
John Magnuson (monthly)
Holger Lippert
Hubert Huber
David Blum
Noam Kfir
Mats gårdstad friberg
Jesper Frickmann
Alan Bunker
Emanuel Kircher
Barry Andersen
Gabriel Formanek
Timothy Justiniano
Kelvin Garcia Urbina
Jan Lau
Choon Wei Jonathan Tan
Daniel Navas
Ray Moss
Markus Frielingsdorf
Michael Hirschauer
Jesse Frey
Philipp Koch
Robert Rubio
Dennis G Miller
Leonardo Garcia Osuna
Antonio Carrasco Pastor
Musa Pinar
Jens Moder
Josef de Beer
Chad Mofford
Pim Pouw
Kenth Jonsson
Gordon Westfall
Jean-Michel Saves
Roberto Orsello
Luboš Konvalinka
Lawrence Dorn
Michael Dittmann
Bernd Schmiedel
Raoul Piccioli
Uwe Probst
Glendon Satchell
Trevor Collins
Horst Grashauser
Miguel José Cárdenas Herrera
Mike Jennings
José Bernardo
Carlos Dangle
Gordon Evans
Pablo Peinado Abad
Carl Payne
Adam Sosnowski
Гасак Сергей
SaltCtyRacingFPV
Georg Bernhardt
James Mildenhall
Dave Plummer
Ivan Mokris
Patrick Daniels
Stuart Olson
Cory Znebel
Andrey Yarovoy
Christian Pons
Burt Pickard-Richardson
Michal Mesaros
Conrad Young
Martin Mathes
Jens Rainer Hansen
Mark Trible
Marc Dubois
Alan Wilkins
Daniel Hryciuk
Thomas Fox
Sidney B Harden
Augustas Sereika
David Belletete
Karl-Heinz Behn
Lena Hjort
Jan Langhorst
Alberto Scotti
John Rock
Adam Kouse
Ricardo Martins
Noel Irwin
Christoph Rausch
Anthony Hrabusicky
Sergio Tondini
Aldo Visentin
Greg Wilson
Mark Sutton
Lukas Kana
Peter Newman
Kevin Cave
Arold Reinders
Jason Plant
John Beech
Ian Parris
Danny Music
Eric Bissonnette
Riso LTD
William Booth
Ferenc Kunkli
Offer Shmuely
Troy Atneosen
Long Technologies
John Jaugilas
Jan-Hinrich Klee
Hans-Reinhard Mette
Alejandro Casals Oliver
David Homewood
John Dunning
Konrad Helbach
Bernard Delpy
Raymond Ellsworth
Bogdan Musial
Гасак Сергей
Philip Garcia
Helder Simoes
Thomas Blanchin
Jean-Luc Mesnier
Michael Bajer
David Homewood
Marc Sanders
Буров Александр
Rudy T'Jolleyn
Jay Watkins
Blaz Vodopivec
David De Salvo
Willem Verschoren
Dennis Kathrens
Alan Aucote
Richard Jerome Danstrom
David Garcia-Mendia
Mark Jones
John Zseleczky
Xiao Sun
Glenn Harvey
Albrecht Friebel
Gunter Klemke
Travis McCarthy
Franz Zier
Ian Contessa
Sean Sadler
Richard F Janczak
Mateusz Dziadosz
Thomas Merchant
M L Perkins
Stefano Boggia
Новоселов Юрий
James Rhodes
Peter Gaskill
Jacques Temey
Anthony Challis
Gerard Falaise
George McGinnis
Antoine Soulie
Tjeerd Jager
Bertold Van den Bergh
Stefanie Zerbe
James Mandelbaum
Javier J. Cordovez
Jess Barkley
Schneider Modell
Michael Hasselgaard
Thomas Young
Непочатов Алексей
Thomas Goebel
Joseph Macias
Paw Melin-Nielsen
Liam O'Brien
Ronald B Backman
Corvus Inspection Services Inc
Stuart Posnett
Clark Emerick
Helmut Sippel
Jhon Lennon Silva do Nascimento
Peter McCarthy
Bob Brown
Claude Lawyer
Peter Fithern
Michael Hoffman
Tim Smith
OpenSki Institute
Simon Melov
Richard Podolsky
James Wilson
John Norrbin
James Goins
Phillip Nguyen
Jeffrey M Engel
Richard Marotto
Greg Bell
Scott Geer
Thomas Abshier
Ernst Camenzind
Radomir Sterba
Ignacio Barrio
Bradley Murchie
Emmanuel Balintec
Rowell Torres
Christopher Kokis
Ken Bryan
Eric Yoder
Olav Roth
Rowell Torres
Christopher Kokis
Ken Bryan
Glenn Noonan
Michael Jakob
Dean Berg
David Hankins
Gary Cripps
+8
View File
@@ -343,6 +343,12 @@ if(PCB STREQUAL X7 AND PCBREV STREQUAL ACCESS)
set(FLAVOUR x7access)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12)
set(FLAVOUR t12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TLITE)
set(FLAVOUR tlite)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12)
set(FLAVOUR tx12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T8)
set(FLAVOUR t8)
elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019)
set(FLAVOUR x9d+2019)
elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS)
@@ -513,6 +519,8 @@ IF(APPLE)
# Use a non standard Info.plist that adds Retina support flags
set_target_properties(${COMPANION_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/companion/targets/mac/MacOSXBundleInfo.plist.in)
set_target_properties(${SIMULATOR_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/companion/targets/mac/MacOSXBundleInfo.plist.in)
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.opentx.companion")
INSTALL(TARGETS ${COMPANION_NAME}
BUNDLE DESTINATION . COMPONENT Runtime
+33
View File
@@ -179,6 +179,39 @@
<file>images/simulator/JumperT12/JumperT12-x.png</file>
<file>images/simulator/JumperT12/JumperT12-center.png</file>
<file>images/simulator/JumperT12/JumperT12-top.png</file>
<file>images/simulator/JumperTLITE/bottom.png</file>
<file>images/simulator/JumperTLITE/bottom_right.png</file>
<file>images/simulator/JumperTLITE/bottom_left.png</file>
<file>images/simulator/JumperTLITE/left.png</file>
<file>images/simulator/JumperTLITE/left_top.png</file>
<file>images/simulator/JumperTLITE/left_bottom.png</file>
<file>images/simulator/JumperTLITE/right.png</file>
<file>images/simulator/JumperTLITE/right_top.png</file>
<file>images/simulator/JumperTLITE/right_bottom.png</file>
<file>images/simulator/JumperTLITE/top.png</file>
<file>images/simulator/TX12/left.png</file>
<file>images/simulator/TX12/left-pageup.png</file>
<file>images/simulator/TX12/left-pagedn.png</file>
<file>images/simulator/TX12/left-rtn.png</file>
<file>images/simulator/TX12/left-sys.png</file>
<file>images/simulator/TX12/left-tele.png</file>
<file>images/simulator/TX12/right.png</file>
<file>images/simulator/TX12/right-ent.png</file>
<file>images/simulator/TX12/right-mdl.png</file>
<file>images/simulator/TX12/bottom.png</file>
<file>images/simulator/TX12/top.png</file>
<file>images/simulator/T8/left.png</file>
<file>images/simulator/T8/left-pageup.png</file>
<file>images/simulator/T8/left-pagedn.png</file>
<file>images/simulator/T8/left-rtn.png</file>
<file>images/simulator/T8/left-sys.png</file>
<file>images/simulator/T8/right.png</file>
<file>images/simulator/T8/right-ent.png</file>
<file>images/simulator/T8/right-mdl.png</file>
<file>images/simulator/T8/right-up.png</file>
<file>images/simulator/T8/right-dn.png</file>
<file>images/simulator/T8/bottom.png</file>
<file>images/simulator/T8/top.png</file>
<file>images/simulator/JumperT16/left.png</file>
<file>images/simulator/JumperT16/right.png</file>
<file>images/simulator/JumperT16/top.png</file>
+1
View File
@@ -71,6 +71,7 @@
#define CPN_STR_APP_SETTINGS_FILTER CPN_STR_APP_SETTINGS_FILES % " (*.ini)"
#define CPN_STR_UNKNOWN_ITEM "???"
#define CPN_STR_NONE_ITEM "----"
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
+4 -4
View File
@@ -1,12 +1,12 @@
set(datamodels_SRCS
rawitemdatamodels.cpp
rawitemfilteredmodel.cpp
compounditemmodels.cpp
filtereditemmodels.cpp
)
set(datamodels_HDRS
rawitemdatamodels.h
rawitemfilteredmodel.h
compounditemmodels.h
filtereditemmodels.h
)
qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS})
@@ -0,0 +1,758 @@
/*
* 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.
*/
#include "compounditemmodels.h"
#include "generalsettings.h"
#include "eeprominterface.h"
#include "modeldata.h"
#include "adjustmentreference.h"
// static
QString AbstractItemModel::idToString(const int value)
{
switch (value) {
case IMID_Unknown:
return "Unknown";
case IMID_RawSource:
return "RawSource";
case IMID_RawSwitch:
return "RawSwitch";
case IMID_Curve:
return "Curve";
case IMID_GVarRef:
return "GVarRef";
case IMID_ThrSource:
return "ThrSource";
case IMID_CustomFuncAction:
return "CustomFuncAction";
case IMID_CustomFuncResetParam:
return "CustomFuncResetParam";
case IMID_TeleSource:
return "TeleSource";
case IMID_RssiSource:
return "RssiSource";
case IMID_CurveRefType:
return "CurveRefType";
case IMID_CurveRefFunc:
return "CurveRefFunc";
default:
return "Custom";
}
}
// static
void AbstractItemModel::dumpItemModelContents(AbstractItemModel * itemModel)
{
if (itemModel) {
qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName();
for (int i = 0; i < itemModel->rowCount(); ++i) {
qDebug() << "row:" << i
<< "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString()
<< "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt()
<< "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool()
<< "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt()
<< "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt();
}
}
else
qDebug() << "Error: model not of class AbstractItemModel";
}
//
// AbstractStaticItemModel
//
void AbstractStaticItemModel::loadItemList()
{
foreach (const ListItem *item, itemList) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(item->text);
modelItem->setData(item->id, IMDR_Id);
modelItem->setData(item->type, IMDR_Type);
modelItem->setData(item->flags, IMDR_Flags);
modelItem->setData(item->isAvailable, IMDR_Available);
appendRow(modelItem);
}
itemList.clear();
};
//
// RawSourceItemModel
//
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RawSource);
setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts));
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
for (int i = 0; i < firmware->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, firmware->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, firmware->getCapability(Sensors) * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, firmware->getCapability(Gvars));
}
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
{
item->setText(src.toString(modelData, generalSettings, boardType));
item->setData(src.isAvailable(modelData, generalSettings, boardType), IMDR_Available);
}
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
{
for (int i = start; i < start + count; i++) {
const RawSource src = RawSource(type, i);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(src.toValue(), IMDR_Id);
modelItem->setData(type, IMDR_Type);
modelItem->setData(group, IMDR_Flags);
setDynamicItemData(modelItem, src);
appendRow(modelItem);
}
}
void RawSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// RawSwitchItemModel
//
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RawSwitch);
setUpdateMask(IMUE_FlightModes | IMUE_LogicalSwitches | IMUE_TeleSensors);
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_ACT, -1);
addItems(SWITCH_TYPE_SENSOR, -firmware->getCapability(Sensors));
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions));
// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_TIMER_MODE, 5);
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, firmware->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, firmware->getCapability(Sensors));
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
addItems(SWITCH_TYPE_ACT, 1);
}
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
{
item->setText(rsw.toString(boardType, generalSettings, modelData));
item->setData(rsw.isAvailable(modelData, generalSettings, boardType), IMDR_Available);
}
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
{
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
// handle exceptions in RawSwitch() index values
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
// determine cotext flags
int context = RawSwitch::AllSwitchContexts;
switch (type) {
case SWITCH_TYPE_FLIGHT_MODE:
context &= ~RawSwitch::MixesContext;
// fallthrough
case SWITCH_TYPE_VIRTUAL:
case SWITCH_TYPE_SENSOR:
context &= ~RawSwitch::GlobalFunctionsContext;
break;
case SWITCH_TYPE_TIMER_MODE:
context = RawSwitch::TimersContext;
break;
case SWITCH_TYPE_NONE:
context &= ~RawSwitch::TimersContext;
break;
case SWITCH_TYPE_ON:
case SWITCH_TYPE_ONE:
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
break;
default:
break;
}
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
RawSwitch rs(type, i + rawIdxAdj);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(rs.toValue(), IMDR_Id);
modelItem->setData(type, IMDR_Type);
modelItem->setData(context, IMDR_Flags);
setDynamicItemData(modelItem, rs);
appendRow(modelItem);
}
}
void RawSwitchItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// CurveItemModel
//
CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_Curve);
if (!modelData)
return;
setUpdateMask(IMUE_Curves);
const int count = firmware->getCapability(NumCurves);
for (int i = -count ; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CurveItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, value);
item->setText(cr.toString(modelData, false));
item->setData(cr.isAvailable(), IMDR_Available);
}
void CurveItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// GVarReferenceItemModel
//
GVarReferenceItemModel::GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_GVarRef);
if (!modelData)
return;
setUpdateMask(IMUE_GVars | IMUE_FlightModes | IMUE_LogicalSwitches);
const int count = firmware->getCapability(Gvars);
if (count > 0) {
addItems(-count);
addItems(count);
}
}
void GVarReferenceItemModel::addItems(int count)
{
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
QStandardItem * modelItem = new QStandardItem();
AdjustmentReference ar(AdjustmentReference::ADJUST_REF_GVAR, i);
modelItem->setData(ar.toValue(), IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, ar);
appendRow(modelItem);
}
}
void GVarReferenceItemModel::setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const
{
item->setText(ar.toString(modelData, false));
item->setData(ar.isAvailable(), IMDR_Available);
}
void GVarReferenceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), AdjustmentReference(item(i)->data(IMDR_Id).toInt()));
emit updateComplete();
}
}
//
// ThrottleSourceItemModel
//
ThrottleSourceItemModel::ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_ThrSource);
if (!modelData)
return;
setUpdateMask(IMUE_Timers | IMUE_Inputs | IMUE_TeleSensors);
for (int i = 0; i < modelData->thrTraceSrcCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void ThrottleSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(modelData->thrTraceSrcToString(value));
item->setData(modelData->isThrTraceSrcAvailable(generalSettings, value), IMDR_Available);
}
void ThrottleSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// CustomFuncActionItemModel
//
CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CustomFuncAction);
setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts));
for (int i = 0; i < AssignFunc::FuncCount; i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(CustomFunctionData::funcContext(i), IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(CustomFunctionData::funcToString((AssignFunc)value, modelData));
item->setData(CustomFunctionData::isFuncAvailable(value), IMDR_Available);
}
void CustomFuncActionItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// CustomFuncResetParamItemModel
//
CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CustomFuncResetParam);
setUpdateMask(IMUE_TeleSensors | IMUE_Timers);
for (int i = 0; i < CustomFunctionData::resetParamCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(CustomFunctionData::resetToString(value, modelData));
item->setData(CustomFunctionData::isResetParamAvailable(value, modelData), IMDR_Available);
}
void CustomFuncResetParamItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i)
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
emit updateComplete();
}
}
//
// TelemetrySourceItemModel
//
TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_TeleSource);
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
const int count = firmware->getCapability(Sensors);
for (int i = -count; i <= count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(SensorData::sourceToString(modelData, value));
item->setData(SensorData::isSourceAvailable(modelData, value), IMDR_Available);
}
void TelemetrySourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i) {
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}
emit updateComplete();
}
}
//
// RssiSourceItemModel
//
RssiSourceItemModel::RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_RssiSource);
if (!modelData)
return;
setUpdateMask(IMUE_TeleSensors | IMUE_Modules);
for (int i = 0; i <= firmware->getCapability(Sensors); ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}
void RssiSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(SensorData::rssiSensorToString(modelData, value));
item->setData(SensorData::isRssiSensorAvailable(modelData, value), IMDR_Available);
}
void RssiSourceItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();
for (int i = 0; i < rowCount(); ++i) {
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}
emit updateComplete();
}
}
//
// CurveRefTypeItemModel
//
CurveRefTypeItemModel::CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CurveRefType);
for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(CurveReference::typeToString((CurveReference::CurveRefType)i));
modelItem->setData(i, IMDR_Id);
modelItem->setData(CurveReference::isTypeAvailable((CurveReference::CurveRefType)i), IMDR_Available);
appendRow(modelItem);
}
}
//
// CurveRefFuncItemModel
//
CurveRefFuncItemModel::CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_CurveRefFunc);
for (int i = 1; i <= CurveReference::functionCount(); i++) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(CurveReference::functionToString(i));
modelItem->setData(i, IMDR_Id);
modelItem->setData(CurveReference::isFunctionAvailable(i), IMDR_Available);
appendRow(modelItem);
}
}
//
// PrecisionItemModel
//
PrecisionItemModel::PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix, const bool placeholders) :
AbstractStaticItemModel()
{
for (int i = minDecimals, j = maxDecimals; j >= 0; i++, j--) {
QString str = QString("0.%1").arg(QString(i, '0'));
if (placeholders)
str.append(QString(j, '_'));
if (!suffix.isEmpty())
str.append(QString(" %1").arg(suffix));
QStandardItem * modelItem = new QStandardItem();
modelItem->setText(str);
modelItem->setData(i, IMDR_Id);
modelItem->setData(true, IMDR_Available);
appendRow(modelItem);
}
}
//
// CompoundItemModelFactory
//
CompoundItemModelFactory::CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData) :
generalSettings(generalSettings),
modelData(modelData)
{
firmware = getCurrentFirmware();
board = new Boards(getCurrentBoard());
boardType = getCurrentBoard();
}
CompoundItemModelFactory::~CompoundItemModelFactory()
{
unregisterItemModels();
delete board;
}
void CompoundItemModelFactory::addItemModel(const int id)
{
switch (id) {
case AbstractItemModel::IMID_RawSource:
registerItemModel(new RawSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_RawSwitch:
registerItemModel(new RawSwitchItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_Curve:
registerItemModel(new CurveItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_GVarRef:
registerItemModel(new GVarReferenceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_ThrSource:
registerItemModel(new ThrottleSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CustomFuncAction:
registerItemModel(new CustomFuncActionItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CustomFuncResetParam:
registerItemModel(new CustomFuncResetParamItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_TeleSource:
registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_RssiSource:
registerItemModel(new RssiSourceItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CurveRefType:
registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_CurveRefFunc:
registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType));
break;
default:
qDebug() << "Error: unknown item model: id";
break;
}
}
int CompoundItemModelFactory::registerItemModel(AbstractItemModel * itemModel)
{
if (itemModel) {
if (!isItemModelRegistered(itemModel->getId())) {
setSourceId(itemModel);
registeredItemModels.append(itemModel);
return itemModel->getId();
}
else
return itemModel->getId();
}
return -1;
}
void CompoundItemModelFactory::unregisterItemModels()
{
foreach (AbstractItemModel *itemModel, registeredItemModels) {
delete itemModel;
}
}
void CompoundItemModelFactory::unregisterItemModel(const int id)
{
AbstractItemModel * itemModel = getItemModel(id);
if (itemModel)
delete itemModel;
}
AbstractItemModel * CompoundItemModelFactory::getItemModel(const int id) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return itemModel;
}
return nullptr;
}
AbstractItemModel * CompoundItemModelFactory::getItemModel(const QString name) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getName() == name)
return itemModel;
}
return nullptr;
}
bool CompoundItemModelFactory::isItemModelRegistered(const int id) const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return true;
}
return false;
}
void CompoundItemModelFactory::update(const int event)
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
itemModel->update(event);
}
}
void CompoundItemModelFactory::dumpAllItemModelContents() const
{
foreach (AbstractItemModel * itemModel, registeredItemModels) {
AbstractItemModel::dumpItemModelContents(itemModel);
}
}
void CompoundItemModelFactory::setSourceId(AbstractItemModel * itemModel)
{
if (itemModel && itemModel->getId() == AbstractItemModel::IMID_Unknown)
itemModel->setId(AbstractItemModel::IMID_ReservedCount + registeredItemModels.count());
}
@@ -0,0 +1,380 @@
/*
* 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.
*/
#pragma once
#include "rawsource.h"
#include "rawswitch.h"
#include <QStandardItemModel>
class GeneralSettings;
class ModelData;
class AdjustmentReference;
class AbstractItemModel: public QStandardItemModel
{
Q_OBJECT
public:
enum ItemModelId {
IMID_Unknown,
IMID_RawSource,
IMID_RawSwitch,
IMID_Curve,
IMID_GVarRef,
IMID_ThrSource,
IMID_CustomFuncAction,
IMID_CustomFuncResetParam,
IMID_TeleSource,
IMID_RssiSource,
IMID_CurveRefType,
IMID_CurveRefFunc,
IMID_ReservedCount,
IMID_Custom
};
Q_ENUM(ItemModelId)
enum ItemModelDataRoles {
IMDR_Id = Qt::UserRole,
IMDR_Type,
IMDR_Flags,
IMDR_Available
};
Q_ENUM(ItemModelDataRoles)
enum ItemModelDataGroups {
IMDG_None = 0x01,
IMDG_Negative = 0x02,
IMDG_Positive = 0x04
};
Q_ENUM(ItemModelDataGroups)
enum ItemModelUpdateEvent {
IMUE_None = 0,
IMUE_SystemRefresh = 1 << 0,
IMUE_Channels = 1 << 1,
IMUE_Curves = 1 << 2,
IMUE_FlightModes = 1 << 3,
IMUE_GVars = 1 << 4,
IMUE_Inputs = 1 << 5,
IMUE_LogicalSwitches = 1 << 6,
IMUE_Scripts = 1 << 7,
IMUE_TeleSensors = 1 << 8,
IMUE_Timers = 1 << 9,
IMUE_Modules = 1 << 10,
IMUE_All = IMUE_SystemRefresh | IMUE_Channels | IMUE_Curves | IMUE_FlightModes | IMUE_GVars | IMUE_Inputs |
IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers | IMUE_Modules
};
Q_ENUM(ItemModelUpdateEvent)
explicit AbstractItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
QStandardItemModel(nullptr),
generalSettings(generalSettings),
modelData(modelData),
firmware(firmware),
board(board),
boardType(boardType),
m_id(IMID_Unknown),
m_name(""),
m_updateMask(IMUE_None)
{}
virtual ~AbstractItemModel() {}
void setId(int id) { m_id = id; }
int getId () const { return m_id; }
bool isReservedModelId() const { return m_id > IMID_Unknown && m_id < IMID_ReservedCount; }
void setName(QString name) { m_name = name; }
QString getName() const { return isReservedModelId() ? idToString(m_id) : m_name; }
void setUpdateMask(const int mask) { m_updateMask = mask; }
int getUpdateMask() const { return m_updateMask; }
inline bool doUpdate(const int event) const { return m_updateMask & event; }
AbstractItemModel * getItemModel(const int id) const;
static void dumpItemModelContents(AbstractItemModel * itemModel);
public slots:
virtual void update(const int event = IMUE_SystemRefresh) = 0;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
Firmware * firmware;
const Boards * board;
const Board::Type boardType;
private:
int m_id = IMID_Unknown;
QString m_name = "";
int m_updateMask = IMUE_None;
static QString idToString(const int value);
};
class AbstractStaticItemModel: public AbstractItemModel
{
Q_OBJECT
public:
explicit AbstractStaticItemModel(const GeneralSettings * const generalSettings = nullptr, const ModelData * const modelData = nullptr,
Firmware * firmware = nullptr, const Boards * const board = nullptr,
const Board::Type boardType = Board::BOARD_UNKNOWN) :
AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {}
virtual ~AbstractStaticItemModel() {};
inline void appendToItemList(QString text, int id, bool isAvailable = true, int type = 0, int flags = 0)
{ itemList.append(new ListItem(text, id, isAvailable, type, flags)); }
void loadItemList();
public slots:
virtual void update(const int event) override final {}
protected:
struct ListItem
{
QString text;
int id;
bool isAvailable;
int type;
int flags;
ListItem() {}
ListItem(QString p_text, int p_id, bool p_isAvailable, int p_type, int p_flags) :
text(p_text), id(p_id), isAvailable(p_isAvailable), type(p_type), flags(p_flags) {}
};
QVector<ListItem *> itemList;
};
class AbstractDynamicItemModel: public AbstractItemModel
{
Q_OBJECT
public:
explicit AbstractDynamicItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {}
virtual ~AbstractDynamicItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) {}
signals:
void aboutToBeUpdated();
void updateComplete();
};
class RawSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RawSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
};
class RawSwitchItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RawSwitchItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
void addItems(const RawSwitchType & type, int count);
};
class CurveItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class GVarReferenceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~GVarReferenceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const;
void addItems(int count);
};
class ThrottleSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~ThrottleSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CustomFuncActionItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CustomFuncActionItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CustomFuncResetParamItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CustomFuncResetParamItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class TelemetrySourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~TelemetrySourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class RssiSourceItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit RssiSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~RssiSourceItemModel() {};
public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;
protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};
class CurveRefTypeItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveRefTypeItemModel() {};
};
class CurveRefFuncItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~CurveRefFuncItemModel() {};
};
class PrecisionItemModel : public AbstractStaticItemModel
{
Q_OBJECT
public:
explicit PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix = "", const bool placeholders = false);
virtual ~PrecisionItemModel() {};
};
//
// CompoundItemModelFactory
//
class CompoundItemModelFactory
{
public:
CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData);
virtual ~CompoundItemModelFactory();
void addItemModel(const int id);
int registerItemModel(AbstractItemModel * itemModel);
void unregisterItemModels();
void unregisterItemModel(const int id);
bool isItemModelRegistered(const int id) const;
AbstractItemModel * getItemModel(const int id) const;
AbstractItemModel * getItemModel(const QString name) const;
void update(const int event = AbstractItemModel::IMUE_SystemRefresh);
void dumpAllItemModelContents() const;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
Firmware * firmware;
Boards * board;
Board::Type boardType;
QVector<AbstractItemModel *> registeredItemModels;
private:
void setSourceId(AbstractItemModel * itemModel);
};
@@ -0,0 +1,252 @@
/*
* 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.
*/
#include "filtereditemmodels.h"
FilteredItemModel::FilteredItemModel(AbstractItemModel * sourceModel, int flags) :
QSortFilterProxyModel(nullptr),
filterFlags(0),
m_id(0),
m_name("")
{
setFilterRole(AbstractItemModel::IMDR_Available);
setFilterKeyColumn(0);
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sourceModel);
if (itemModel) {
connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &FilteredItemModel::onAboutToBeUpdated);
connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &FilteredItemModel::onUpdateComplete);
}
}
void FilteredItemModel::setFilterFlags(int flags)
{
if (filterFlags != flags) {
filterFlags = flags;
invalidateFilter();
}
}
bool FilteredItemModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
return false;
if (!filterFlags)
return true;
bool ok;
const int flags = sourceModel()->data(srcIdx, AbstractItemModel::IMDR_Flags).toInt(&ok);
return (ok && (!flags || (filterFlags & flags)));
}
void FilteredItemModel::update() const
{
AbstractDynamicItemModel * itemModel = qobject_cast<AbstractDynamicItemModel *>(sourceModel());
if (itemModel)
itemModel->update();
}
void FilteredItemModel::onAboutToBeUpdated()
{
emit aboutToBeUpdated();
}
void FilteredItemModel::onUpdateComplete()
{
emit updateComplete();
}
// static
void FilteredItemModel::dumpItemModelContents(FilteredItemModel * itemModel)
{
if (itemModel) {
qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName();
for (int i = 0; i < itemModel->rowCount(); ++i) {
qDebug() << "row:" << i
<< "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString()
<< "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt()
<< "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool()
<< "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt()
<< "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt();
}
}
else
qDebug() << "Error: model not of class FilteredItemModel";
}
//
// FilteredItemModelFactory
//
FilteredItemModelFactory::FilteredItemModelFactory()
{
}
FilteredItemModelFactory::~FilteredItemModelFactory()
{
unregisterItemModels();
}
int FilteredItemModelFactory::registerItemModel(FilteredItemModel * itemModel, const QString name, const int id)
{
if (itemModel) {
if (isItemModelRegistered(name)) {
qDebug() << "Error: item model already registered with name:" << name;
return 0;
}
else if (id > -1 && isItemModelRegistered(id)) {
qDebug() << "Error: item model already registered with id:" << id;
return 0;
}
else {
int fid = id;
if (fid < 0) {
fid = registeredItemModels.count() + 1;
AbstractItemModel * mdl = qobject_cast<AbstractItemModel *>(itemModel->sourceModel());
if (mdl) {
fid += mdl->getId() * 128;
}
}
itemModel->setId(fid);
itemModel->setName(name);
registeredItemModels.append(itemModel);
return fid;
}
}
qDebug() << "Error: invalid filtered item model pointer";
return 0;
}
void FilteredItemModelFactory::unregisterItemModels()
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
delete itemModel;
}
}
void FilteredItemModelFactory::unregisterItemModel(const int id)
{
FilteredItemModel * itemModel = getItemModel(id);
if (itemModel)
delete itemModel;
}
bool FilteredItemModelFactory::isItemModelRegistered(const int id) const
{
return getItemModel(id);
}
bool FilteredItemModelFactory::isItemModelRegistered(const QString name) const
{
return getItemModel(name);
}
FilteredItemModel * FilteredItemModelFactory::getItemModel(const int id) const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
if (itemModel->getId() == id)
return itemModel;
}
return nullptr;
}
FilteredItemModel * FilteredItemModelFactory::getItemModel(const QString name) const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
if (itemModel->getName() == name)
return itemModel;
}
return nullptr;
}
void FilteredItemModelFactory::update()
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
itemModel->update();
}
}
void FilteredItemModelFactory::dumpItemModelContents(const int id) const
{
FilteredItemModel::dumpItemModelContents(getItemModel(id));
}
void FilteredItemModelFactory::dumpItemModelContents(const QString name) const
{
FilteredItemModel::dumpItemModelContents(getItemModel(name));
}
void FilteredItemModelFactory::dumpAllItemModelContents() const
{
foreach (FilteredItemModel * itemModel, registeredItemModels) {
FilteredItemModel::dumpItemModelContents(itemModel);
}
}
//
// CurveRefFilteredFactory
//
CurveRefFilteredFactory::CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags, const int gvarRefFlags)
{
if (!sharedItemModels) {
qDebug() << "Error: invalid compound item model factory pointer";
return;
}
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve), curveFlags),
fidToString(CRFIM_CURVE), CRFIM_CURVE);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef), gvarRefFlags),
fidToString(CRFIM_GVARREF), CRFIM_GVARREF);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefType)),
fidToString(CRFIM_TYPE), CRFIM_TYPE);
registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefFunc)),
fidToString(CRFIM_FUNC), CRFIM_FUNC);
}
CurveRefFilteredFactory::~CurveRefFilteredFactory()
{
}
// static
QString CurveRefFilteredFactory::fidToString(const int value)
{
switch(value) {
case CRFIM_CURVE:
return "Curves";
case CRFIM_GVARREF:
return "Global Variables";
case CRFIM_TYPE:
return "Types";
case CRFIM_FUNC:
return "Functions";
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
@@ -0,0 +1,115 @@
/*
* 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 FILTEREDITEMMODELS_H
#define FILTEREDITEMMODELS_H
#include "compounditemmodels.h"
#include <QObject>
#include <QSortFilterProxyModel>
#include <QString>
class FilteredItemModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
enum DataFilters {
AllFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None | AbstractItemModel::IMDG_Positive,
AllExcludeNoneFilter = AllFilter &~ AbstractItemModel::IMDG_None,
NegativeFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None,
NegativeExcludeNoneFilter = AbstractItemModel::IMDG_Negative,
PositiveFilter = AbstractItemModel::IMDG_Positive | AbstractItemModel::IMDG_None,
PositiveExcludeNoneFilter = AbstractItemModel::IMDG_Positive
};
Q_ENUM(DataFilters)
explicit FilteredItemModel(AbstractItemModel * sourceModel, int flags);
explicit FilteredItemModel(AbstractItemModel * sourceModel) :
FilteredItemModel(sourceModel, 0) {}
virtual ~FilteredItemModel() {};
void setId(int id) { m_id = id; }
int getId() const { return m_id; };
void setName(QString name) { m_name = name; }
QString getName() const { return m_name; }
static void dumpItemModelContents(FilteredItemModel * itemModel);
public slots:
void setFilterFlags(int flags);
void update() const;
void onAboutToBeUpdated();
void onUpdateComplete();
signals:
void aboutToBeUpdated();
void updateComplete();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
private:
int m_id = 0;
QString m_name = "";
};
class FilteredItemModelFactory
{
public:
explicit FilteredItemModelFactory();
virtual ~FilteredItemModelFactory();
int registerItemModel(FilteredItemModel * itemModel, const QString name, const int id = -1);
void unregisterItemModels();
void unregisterItemModel(const int id);
bool isItemModelRegistered(const int id) const;
bool isItemModelRegistered(const QString name) const;
FilteredItemModel * getItemModel(const int id) const;
FilteredItemModel * getItemModel(const QString name) const;
void update();
void dumpItemModelContents(const int id) const;
void dumpItemModelContents(const QString name) const;
void dumpAllItemModelContents() const;
protected:
QVector<FilteredItemModel *> registeredItemModels;
};
class CurveRefFilteredFactory : public FilteredItemModelFactory
{
public:
enum FilteredItemModelId {
CRFIM_CURVE,
CRFIM_GVARREF,
CRFIM_TYPE,
CRFIM_FUNC
};
explicit CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags = 0, const int gvarRefFlags = 0);
virtual ~CurveRefFilteredFactory();
static QString fidToString(const int value);
};
#endif // FILTEREDITEMMODELS_H
@@ -1,173 +0,0 @@
/*
* 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.
*/
#include "rawitemdatamodels.h"
#include "generalsettings.h"
#include "eeprominterface.h"
#include "modeldata.h"
RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
const Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1);
for (int i=0; i < fw->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board.getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs));
addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs));
addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5);
addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, CPN_MAX_SENSORS * 3);
addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars));
}
void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const
{
Board::Type board = getCurrentBoard();
item->setText(src.toString(modelData, generalSettings, board));
item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start)
{
for (int i = start; i < start + count; i++) {
const RawSource src = RawSource(type, i);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(src.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(group, ItemFlagsRole);
setDynamicItemData(modelItem, src);
appendRow(modelItem);
}
}
void RawSourceItemModel::update() const
{
for (int i=0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt()));
}
//
// RawSwitchItemModel
//
RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) :
AbstractRawItemDataModel(generalSettings, modelData, parent)
{
Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
// Descending switch direction: NOT (!) switches
addItems(SWITCH_TYPE_ACT, -1);
addItems(SWITCH_TYPE_SENSOR, -CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_TELEMETRY, -1);
addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions));
// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_TIMER_MODE, 5);
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders));
addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes));
addItems(SWITCH_TYPE_TELEMETRY, 1);
addItems(SWITCH_TYPE_SENSOR, CPN_MAX_SENSORS);
addItems(SWITCH_TYPE_ON, 1);
addItems(SWITCH_TYPE_ONE, 1);
addItems(SWITCH_TYPE_ACT, 1);
}
void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const
{
const Board::Type board = getCurrentBoard();
item->setText(rsw.toString(board, generalSettings, modelData));
item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole);
}
void RawSwitchItemModel::addItems(const RawSwitchType & type, int count)
{
// Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule:
const static QVector<int> rawSwitchIndexBaseZeroTypes = QVector<int>() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE;
// handle exceptions in RawSwitch() index values
const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0;
// determine cotext flags
int context = RawSwitch::AllSwitchContexts;
switch (type) {
case SWITCH_TYPE_FLIGHT_MODE:
context &= ~RawSwitch::MixesContext;
// fallthrough
case SWITCH_TYPE_VIRTUAL:
case SWITCH_TYPE_SENSOR:
context &= ~RawSwitch::GlobalFunctionsContext;
break;
case SWITCH_TYPE_TIMER_MODE:
context = RawSwitch::TimersContext;
break;
case SWITCH_TYPE_NONE:
context &= ~RawSwitch::TimersContext;
break;
case SWITCH_TYPE_ON:
case SWITCH_TYPE_ONE:
context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext;
break;
default:
break;
}
int i = (count < 0 ? count : 1);
count = (i < 0 ? 0 : count + i);
for ( ; i < count; ++i) {
RawSwitch rs(type, i + rawIdxAdj);
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(rs.toValue(), ItemIdRole);
modelItem->setData(type, ItemTypeRole);
modelItem->setData(context, ItemFlagsRole);
setDynamicItemData(modelItem, rs);
appendRow(modelItem);
}
}
void RawSwitchItemModel::update() const
{
for (int i=0; i < rowCount(); ++i)
setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt()));
}
@@ -1,84 +0,0 @@
/*
* 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 RAWITEMDATAMODELS_H
#define RAWITEMDATAMODELS_H
#include "rawsource.h"
#include "rawswitch.h"
#include <QStandardItemModel>
class GeneralSettings;
class ModelData;
class AbstractRawItemDataModel: public QStandardItemModel
{
Q_OBJECT
public:
enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole };
Q_ENUM(DataRoles)
explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
QStandardItemModel(parent),
generalSettings(generalSettings),
modelData(modelData)
{}
public slots:
virtual void update() const = 0;
protected:
const GeneralSettings * generalSettings;
const ModelData * modelData;
};
class RawSourceItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSource & src) const;
void addItems(const RawSourceType & type, const int group, const int count, const int start = 0);
};
class RawSwitchItemModel: public AbstractRawItemDataModel
{
Q_OBJECT
public:
explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr);
public slots:
void update() const override;
protected:
void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const;
void addItems(const RawSwitchType & type, int count);
};
#endif // RAWITEMDATAMODELS_H
@@ -1,74 +0,0 @@
/*
* 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.
*/
#include "rawitemfilteredmodel.h"
#include "rawitemdatamodels.h"
RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) :
QSortFilterProxyModel(parent),
filterFlags(0)
{
setFilterRole(AbstractRawItemDataModel::IsAvailableRole);
setFilterKeyColumn(0);
setFilterFlags(flags);
setDynamicSortFilter(true);
setSourceModel(sourceModel);
}
void RawItemFilteredModel::setFilterFlags(int flags)
{
if (filterFlags != flags) {
filterFlags = flags;
invalidateFilter();
}
}
bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent);
if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool())
return false;
if (!filterFlags)
return true;
bool ok;
const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok);
return (ok && (!flags || (filterFlags & flags)));
}
void RawItemFilteredModel::update() const
{
AbstractRawItemDataModel * model = qobject_cast<AbstractRawItemDataModel *>(sourceModel());
if (model)
model->update();
}
RawSourceFilterItemModel::RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent) :
RawItemFilteredModel(new RawSourceItemModel(generalSettings, modelData, parent), flags, parent)
{
}
RawSwitchFilterItemModel::RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent) :
RawItemFilteredModel(new RawSwitchItemModel(generalSettings, modelData, parent), context, parent)
{
}
@@ -1,74 +0,0 @@
/*
* 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 RAWITEMFILTEREDMODEL_H
#define RAWITEMFILTEREDMODEL_H
#include <QSortFilterProxyModel>
class GeneralSettings;
class ModelData;
class RawSourceItemModel;
class RawSwitchItemModel;
class RawItemFilteredModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr);
explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {}
public slots:
void setFilterFlags(int flags);
void update() const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
int filterFlags;
};
// The specialized "convenience" types below can go away once centralalized RawSource/RawSwitch item models are established.
// These proxy classes will automatically create a source model of the corresponding type.
class RawSwitchFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSwitchFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int context, QObject * parent = nullptr);
};
class RawSourceFilterItemModel: public RawItemFilteredModel
{
Q_OBJECT
public:
using RawItemFilteredModel::RawItemFilteredModel;
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, int flags, QObject * parent = nullptr);
explicit RawSourceFilterItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) :
RawSourceFilterItemModel(generalSettings, modelData, 0, parent) {}
};
#endif // RAWITEMFILTEREDMODEL_H
+2
View File
@@ -39,6 +39,8 @@
#include <QLineEdit>
#include <QMenu>
#include <QSpinBox>
#include <QMessageBox>
#include <QPushButton>
FileSyncDialog::FileSyncDialog(QWidget * parent, const SyncProcess::SyncOptions & syncOptions) :
QDialog(parent),
+15 -2
View File
@@ -2,27 +2,34 @@
set(firmwares_SRCS
adjustmentreference.cpp
boards.cpp
curvedata.cpp
curvereference.cpp
customfunctiondata.cpp
eeprominterface.cpp
generalsettings.cpp
gvardata.cpp
io_data.cpp
input_data.cpp
flightmodedata.cpp
heli_data.cpp
logicalswitchdata.cpp
mixdata.cpp
modeldata.cpp
moduledata.cpp
multiprotocols.cpp
output_data.cpp
radiodata.cpp
radiodataconversionstate.cpp
rawsource.cpp
rawswitch.cpp
sensordata.cpp
telem_data.cpp
timerdata.cpp
afhds3.cpp
ersky9x/ersky9xeeprom.cpp
ersky9x/ersky9xinterface.cpp
opentx/opentxeeprom.cpp
opentx/opentxinterface.cpp
datahelpers.cpp
)
string(REPLACE ".cpp" ".h" firmwares_HDRS "${firmwares_SRCS}")
@@ -32,8 +39,14 @@ list(APPEND firmwares_HDRS
moduledata.h
)
set(firmwares_QT
curvereference.h
)
qt5_wrap_cpp(firmwares_SRCS ${firmwares_QT})
add_library(firmwares ${firmwares_SRCS} ${firmwares_HDRS})
target_link_libraries(firmwares ${CPN_COMMON_LIB} Qt5::Core Qt5::Xml Qt5::Widgets)
target_link_libraries(firmwares ${CPN_COMMON_LIB} datamodels Qt5::Core Qt5::Xml Qt5::Widgets)
target_include_directories(firmwares
PRIVATE
${CMAKE_SOURCE_DIR}
@@ -19,7 +19,7 @@
*/
#include "adjustmentreference.h"
#include "radiodata.h" // for ModelData
#include "modeldata.h"
AdjustmentReference::AdjustmentReference(int value)
{
@@ -76,3 +76,8 @@ QString AdjustmentReference::toString(const ModelData * model, const bool sign)
}
return ret;
}
const bool AdjustmentReference::isAvailable() const
{
return true;
}
@@ -45,6 +45,7 @@ class AdjustmentReference {
bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; }
bool isValid(const int value) const;
QString toString(const ModelData * model = nullptr, const bool sign = false) const;
const bool isAvailable() const;
inline const int toValue() const
{
+96 -17
View File
@@ -79,17 +79,21 @@ uint32_t Boards::getFourCC(Type board)
return 0x3278746F;
case BOARD_JUMPER_T12:
return 0x3D78746F;
case BOARD_JUMPER_TLITE:
return 0x4278746F;
case BOARD_JUMPER_T16:
return 0x3F78746F;
case BOARD_JUMPER_T18:
return 0x4078746F;
case BOARD_RADIOMASTER_TX16S:
return 0x3878746F;
case BOARD_UNKNOWN:
break;
case BOARD_RADIOMASTER_TX12:
return 0x4178746F;
case BOARD_RADIOMASTER_T8:
return 0x4378746F;
default:
return 0;
}
return 0;
}
int Boards::getEEpromSize(Board::Type board)
@@ -111,6 +115,9 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_TARANIS_X9DP_2019:
case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_T8:
return EESIZE_TARANIS;
case BOARD_UNKNOWN:
return EESIZE_MAX;
@@ -121,9 +128,9 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_JUMPER_T18:
case BOARD_RADIOMASTER_TX16S:
return 0;
default:
return 0;
}
return 0;
}
int Boards::getFlashSize(Type board)
@@ -145,6 +152,9 @@ int Boards::getFlashSize(Type board)
case BOARD_TARANIS_X9DP_2019:
case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_T8:
return FSIZE_TARANIS;
case BOARD_HORUS_X12S:
case BOARD_X10:
@@ -177,7 +187,7 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
else if (IS_TARANIS_XLITE(board)) {
else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -187,7 +197,20 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
else if (IS_TARANIS_X7(board)) {
else if (board == BOARD_TARANIS_X7_ACCESS) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_3POS, "SD"},
{SWITCH_2POS, "SF"},
{SWITCH_TOGGLE, "SH"},
{SWITCH_2POS, "SI"}
};
if (index < DIM(switches))
return switches[index];
}
else if (board == BOARD_TARANIS_X7) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -201,6 +224,30 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
else if (IS_RADIOMASTER_TX12(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_TOGGLE, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_TOGGLE, "SD"},
{SWITCH_3POS, "SE"},
{SWITCH_3POS, "SF"},
{SWITCH_2POS, "SI"},
{SWITCH_2POS, "SJ"}
};
if (index < DIM(switches))
return switches[index];
}
else if (IS_RADIOMASTER_T8(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_TOGGLE, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_TOGGLE, "SD"}
};
if (index < DIM(switches))
return switches[index];
}
else if (IS_JUMPER_T12(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
@@ -213,7 +260,23 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
else if (IS_HORUS_OR_TARANIS(board)) {
else if (IS_FAMILY_HORUS_OR_T16(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_3POS, "SC"},
{SWITCH_3POS, "SD"},
{SWITCH_3POS, "SE"},
{SWITCH_2POS, "SF"},
{SWITCH_3POS, "SG"},
{SWITCH_TOGGLE, "SH"},
{SWITCH_2POS, "SI"},
{SWITCH_2POS, "SJ"}
};
if (index < DIM(switches))
return switches[index];
}
else if (IS_TARANIS(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -263,7 +326,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case Pots:
if (IS_TARANIS_X9LITE(board))
return 1;
else if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
else if (IS_JUMPER_TLITE(board))
return 0;
else if (IS_TARANIS_SMALL(board))
return 2;
else if (IS_TARANIS_X9E(board))
return 4;
@@ -289,7 +354,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 0;
case MouseAnalogs:
if (IS_FAMILY_HORUS_OR_T16(board))
if (IS_HORUS_X12S(board))
return 2;
else
return 0;
@@ -316,10 +381,14 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 5;
else if (board == Board::BOARD_TARANIS_X9LITES)
return 7;
else if (IS_TARANIS_X7(board))
else if (board == BOARD_TARANIS_X7_ACCESS)
return 7;
else if (board == BOARD_TARANIS_X7)
return 8;
else if (board == BOARD_JUMPER_TLITE)
return 4;
else if (IS_FAMILY_T12(board))
return 8;
else if (IS_JUMPER_T12(board))
return 6;
else if (IS_TARANIS_XLITE(board))
return 6;
else if (board == Board::BOARD_TARANIS_X9DP_2019)
@@ -334,7 +403,11 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case FactoryInstalledSwitches:
if (IS_TARANIS_X9E(board))
return 8;
if (IS_HORUS_X12S(board))
else if (IS_JUMPER_TLITE(board))
return 4;
else if (IS_FAMILY_T12(board))
return 6;
else if (IS_HORUS_X12S(board))
return 8;
else
return getCapability(board, Switches);
@@ -479,8 +552,6 @@ QString Boards::getBoardName(Board::Type board)
return "Taranis X7/X7S";
case BOARD_TARANIS_X7_ACCESS:
return "Taranis X7/X7S Access";
case BOARD_JUMPER_T12:
return "Jumper T12";
case BOARD_TARANIS_XLITE:
return "Taranis X-Lite";
case BOARD_TARANIS_XLITES:
@@ -509,12 +580,20 @@ QString Boards::getBoardName(Board::Type board)
return "Horus X10/X10S";
case BOARD_X10_EXPRESS:
return "Horus X10/X10S Express";
case BOARD_JUMPER_T12:
return "Jumper T12";
case BOARD_JUMPER_TLITE:
return "Jumper T-Lite";
case BOARD_JUMPER_T16:
return "Jumper T16";
case BOARD_JUMPER_T18:
return "Jumper T18";
case BOARD_RADIOMASTER_TX16S:
return "Radiomaster TX16S";
case BOARD_RADIOMASTER_TX12:
return "Radiomaster TX12";
case BOARD_RADIOMASTER_T8:
return "Radiomaster T8";
default:
return tr("Unknown");
}
+31 -8
View File
@@ -52,10 +52,13 @@ namespace Board {
BOARD_JUMPER_T16,
BOARD_RADIOMASTER_TX16S,
BOARD_JUMPER_T18,
BOARD_RADIOMASTER_TX12,
BOARD_RADIOMASTER_T8,
BOARD_JUMPER_TLITE,
BOARD_TYPE_COUNT,
BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1
};
constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T18;
enum PotType
{
POT_NONE,
@@ -203,6 +206,11 @@ inline bool IS_JUMPER_T12(Board::Type board)
return board == Board::BOARD_JUMPER_T12;
}
inline bool IS_JUMPER_TLITE(Board::Type board)
{
return board == Board::BOARD_JUMPER_TLITE;
}
inline bool IS_JUMPER_T16(Board::Type board)
{
return board == Board::BOARD_JUMPER_T16;
@@ -218,11 +226,26 @@ inline bool IS_RADIOMASTER_TX16S(Board::Type board)
return board == Board::BOARD_RADIOMASTER_TX16S;
}
inline bool IS_RADIOMASTER_TX12(Board::Type board)
{
return board == Board::BOARD_RADIOMASTER_TX12;
}
inline bool IS_RADIOMASTER_T8(Board::Type board)
{
return board == Board::BOARD_RADIOMASTER_T8;
}
inline bool IS_FAMILY_T16(Board::Type board)
{
return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18;
}
inline bool IS_FAMILY_T12(Board::Type board)
{
return board == Board::BOARD_JUMPER_T12 || board == Board::BOARD_RADIOMASTER_TX12 || board == Board::BOARD_RADIOMASTER_T8 || board == Board::BOARD_JUMPER_TLITE;
}
inline bool IS_TARANIS_XLITE(Board::Type board)
{
return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES;
@@ -273,14 +296,14 @@ inline bool IS_TARANIS_X9E(Board::Type board)
return board == Board::BOARD_TARANIS_X9E;
}
inline bool IS_TARANIS(Board::Type board)
{
return IS_TARANIS_X9(board) || IS_TARANIS_X7(board) || IS_TARANIS_X9LITE(board) || IS_TARANIS_XLITE(board) || IS_JUMPER_T12(board);
}
inline bool IS_TARANIS_SMALL(Board::Type board)
{
return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_T12(board);
return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_FAMILY_T12(board);
}
inline bool IS_TARANIS(Board::Type board)
{
return IS_TARANIS_X9(board) || IS_TARANIS_SMALL(board);
}
inline bool IS_HORUS_X10(Board::Type board)
+48
View File
@@ -0,0 +1,48 @@
/*
* 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.
*/
#include "curvedata.h"
#include "radiodata.h"
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i = 0; i < count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}
+56
View File
@@ -0,0 +1,56 @@
/*
* 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.
*/
#pragma once
#include "constants.h"
#include <QtCore>
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN + 1];
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
};
+243 -19
View File
@@ -19,45 +19,269 @@
*/
#include "curvereference.h"
#include "adjustmentreference.h"
#include "helpers.h"
#include "modeldata.h"
#include "filtereditemmodels.h"
#include "helpers.h" // for Helpers::getAdjustmentString()
#include "radiodata.h" // for ModelData
QString CurveReference::toString(const ModelData * model, bool verbose) const
const QString CurveReference::toString(const ModelData * model, bool verbose) const
{
if (value == 0) {
return "----";
}
if (value == 0)
return CPN_STR_NONE_ITEM;
QString ret;
unsigned idx = abs(value) - 1;
switch(type) {
case CURVE_REF_DIFF:
ret = tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_EXPO:
ret = tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
ret = AdjustmentReference(value).toString(model);
break;
case CURVE_REF_FUNC:
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
if (verbose)
ret = tr("Function(%1)").arg(ret);
ret = functionToString(value);
break;
default:
case CURVE_REF_CUSTOM:
if (model)
ret = model->curves[idx].nameToString(idx);
else
ret = CurveData().nameToString(idx);
if (verbose)
ret = tr("Curve(%1)").arg(ret);
if (value < 0)
ret.prepend(CPN_STR_SW_INDICATOR_REV);
break;
default:
return CPN_STR_UNKNOWN_ITEM;
}
if (verbose)
ret = tr(qPrintable(QString(typeToString(type) + "(%1)").arg(ret)));
return ret;
}
const bool CurveReference::isValueNumber() const
{
return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE;
}
const bool CurveReference::isAvailable() const
{
return true;
}
// static
int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar)
{
if (isGVar && (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO))
return AdjustmentReference(AdjustmentReference::ADJUST_REF_GVAR, 1).toValue();
else if (type == CURVE_REF_FUNC)
return 1;
else
return 0;
}
// static
QString CurveReference::typeToString(const CurveRefType type)
{
const QStringList strl = { tr("Diff"), tr("Expo") , tr("Func"), tr("Curve") };
int idx = (int)type;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
// static
QString CurveReference::functionToString(const int value)
{
const QStringList strl = { "x>0", "x<0", "|x|", "f>0", "f<0", "|f|" };
int idx = value - 1;
if (idx < 0 || idx >= strl.count())
return CPN_STR_UNKNOWN_ITEM;
return strl.at(idx);
}
// static
bool CurveReference::isTypeAvailable(const CurveRefType type)
{
bool ret = false;
Firmware * fw = getCurrentFirmware();
switch(type) {
case CURVE_REF_DIFF:
if (fw->getCapability(HasInputDiff))
ret = true;
break;
case CURVE_REF_EXPO:
if (fw->getCapability(HasMixerExpo))
ret = true;
break;
case CURVE_REF_FUNC:
case CURVE_REF_CUSTOM:
ret = true;
break;
}
return ret;
}
// static
bool CurveReference::isFunctionAvailable(const int value)
{
return true;
}
// static
int CurveReference::functionCount()
{
return 6;
}
/*
* CurveReferenceUIManager
*/
CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB,
QComboBox * curveValueCB, CurveReference & curveRef, const ModelData & model,
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) :
QObject(parent),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueSB(curveValueSB),
curveValueCB(curveValueCB),
curveRef(curveRef),
model(model),
lock(false),
filteredModelFactory(curveRefFilteredFactory)
{
hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars);
if (curveTypeCB) {
curveTypeCB->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE));
curveTypeCB->setCurrentIndex(curveTypeCB->findData((int)curveRef.type));
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
}
if (curveGVarCB)
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
if (curveValueSB) {
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged()));
}
if (curveValueCB) {
curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);
curveValueCB->setMaxVisibleItems(10);
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged()));
}
update();
}
CurveReferenceUIManager::~CurveReferenceUIManager()
{
delete filteredModelFactory;
}
#define CURVE_REF_UI_GVAR_SHOW (1<<0)
#define CURVE_REF_UI_VALUE_SHOW (1<<1)
#define CURVE_REF_UI_REF_SHOW (1<<2)
void CurveReferenceUIManager::update()
{
lock = true;
int widgetsMask = 0;
if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) {
if (hasCapabilityGvars)
widgetsMask |= CURVE_REF_UI_GVAR_SHOW;
if (curveRef.isValueNumber()) {
curveGVarCB->setChecked(false);
curveValueSB->setValue(curveRef.value);
widgetsMask |= CURVE_REF_UI_VALUE_SHOW;
}
else {
curveGVarCB->setChecked(true);
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
}
else {
widgetsMask |= CURVE_REF_UI_REF_SHOW;
}
if(curveTypeCB) {
curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type));
curveTypeCB->show();
}
if(curveGVarCB)
curveGVarCB->setVisible(widgetsMask & CURVE_REF_UI_GVAR_SHOW);
if(curveValueSB)
curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW);
if(curveValueCB) {
if (curveRef.isValueReference())
populateValueCB(curveValueCB);
curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW);
}
lock = false;
}
void CurveReferenceUIManager::gvarCBChanged(int state)
{
if (!lock) {
curveRef.value = CurveReference::getDefaultValue(curveRef.type, state);
update();
}
}
void CurveReferenceUIManager::typeChanged(int value)
{
if (!lock) {
CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
curveRef = CurveReference(type, CurveReference::getDefaultValue(type));
update();
}
}
void CurveReferenceUIManager::valueSBChanged()
{
if (!lock) {
curveRef.value = curveValueSB->value();
update();
}
}
void CurveReferenceUIManager::valueCBChanged()
{
if (!lock) {
curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
update();
}
}
void CurveReferenceUIManager::populateValueCB(QComboBox * cb)
{
if (cb) {
switch (curveRef.type) {
case CurveReference::CURVE_REF_DIFF:
case CurveReference::CURVE_REF_EXPO:
cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_GVARREF));
break;
case CurveReference::CURVE_REF_FUNC:
cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_FUNC));
break;
case CurveReference::CURVE_REF_CUSTOM:
cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE));
break;
default:
break;
}
cb->setCurrentIndex(cb->findData(curveRef.value));
}
}
+75 -9
View File
@@ -22,35 +22,101 @@
#define CURVEREFERENCE_H
#include <QtCore>
#include <QComboBox>
#include <QCheckBox>
#include <QSpinBox>
#include <QStandardItemModel>
class ModelData;
class CurveRefFilteredFactory;
class CurveReference {
Q_DECLARE_TR_FUNCTIONS(CurveReference)
public:
enum CurveRefType {
CURVE_REF_DIFF,
CURVE_REF_EXPO,
CURVE_REF_FUNC,
CURVE_REF_CUSTOM
CURVE_REF_CUSTOM,
MAX_CURVE_REF_TYPE = CURVE_REF_CUSTOM
};
enum CurveRefGroups {
NoneGroup = 0x001,
NegativeGroup = 0x002,
PositiveGroup = 0x004,
AllCurveRefGroups = NoneGroup | NegativeGroup | PositiveGroup,
PositiveCurveRefGroups = AllCurveRefGroups &~ NegativeGroup
};
CurveReference() { clear(); }
CurveReference(CurveRefType type, int value):
type(type),
value(value)
{
}
CurveReference(CurveRefType type, int value) : type(type), value(value) { ; }
void clear() { memset(this, 0, sizeof(CurveReference)); }
const bool isEmpty() const { return type == CURVE_REF_DIFF && value == 0; }
const bool isSet() const { return !isEmpty(); }
const bool isValueNumber() const;
const bool isValueReference() const { return !isValueNumber(); }
const QString toString(const ModelData * model = nullptr, bool verbose = true) const;
const bool isAvailable() const;
CurveRefType type;
int value;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
bool isSet() const { return type != CURVE_REF_DIFF || value != 0; }
bool operator == ( const CurveReference & other) const {
return (this->type == other.type) && (this->value == other.value);
}
bool operator != ( const CurveReference & other) const {
return (this->type != other.type) || (this->value != other.value);
}
static int getDefaultValue(const CurveRefType type, const bool isGVar = false);
static QString typeToString(const CurveRefType type);
static QString functionToString(const int value);
static bool isTypeAvailable(const CurveRefType type);
static bool isFunctionAvailable(const int value);
static int functionCount();
};
class CurveReferenceUIManager : public QObject {
Q_OBJECT
public:
explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB,
CurveReference & curve, const ModelData & model, CurveRefFilteredFactory * curveRefFilteredFactory,
QObject * parent = nullptr);
explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model,
CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) :
CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, curve, model, curveRefFilteredFactory, parent) {}
virtual ~CurveReferenceUIManager();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valueSBChanged();
void valueCBChanged();
void update();
private:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QSpinBox *curveValueSB;
QComboBox *curveValueCB;
CurveReference & curveRef;
const ModelData & model;
bool lock;
bool hasCapabilityGvars;
CurveRefFilteredFactory *filteredModelFactory;
void populateValueCB(QComboBox * cb);
};
#endif // CURVEREFERENCE_H
+255 -110
View File
@@ -22,6 +22,17 @@
#include "eeprominterface.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
#include "compounditemmodels.h"
void CustomFunctionData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncBacklight || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
}
}
void CustomFunctionData::clear()
{
@@ -36,17 +47,24 @@ bool CustomFunctionData::isEmpty() const
return (swtch.type == SWITCH_TYPE_NONE);
}
QString CustomFunctionData::nameToString(int index, bool globalContext) const
// static
QString CustomFunctionData::nameToString(const int index, const bool globalContext)
{
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true);
return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index + 1, 0, true);
}
QString CustomFunctionData::funcToString(const ModelData * model) const
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
return funcToString(func, model);
}
// static
QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData * model)
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast)
return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer)
return tr("Trainer");
return tr("Trainer Sticks");
else if (func == FuncTrainerRUD)
return tr("Trainer RUD");
else if (func == FuncTrainerELE)
@@ -65,8 +83,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
return tr("Haptic");
else if (func == FuncReset)
return tr("Reset");
else if (func >= FuncSetTimer1 && func <= FuncSetTimer3)
return tr("Set Timer %1").arg(func-FuncSetTimer1+1);
else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast)
return tr("Set %1").arg(RawSource(SOURCE_TYPE_SPECIAL, SOURCE_TYPE_SPECIAL_TIMER1_IDX + func - FuncSetTimer1).toString(model));
else if (func == FuncVario)
return tr("Vario");
else if (func == FuncPlayPrompt)
@@ -76,7 +94,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncPlayValue)
return tr("Play Value");
else if (func == FuncPlayScript)
return tr("Play Script");
return tr("Lua Script");
else if (func == FuncLogs)
return tr("SD Logs");
else if (func == FuncVolume)
@@ -90,106 +108,44 @@ QString CustomFunctionData::funcToString(const ModelData * model) const
else if (func == FuncBackgroundMusicPause)
return tr("Background Music Pause");
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafeInternalModule)
return tr("SetFailsafe Int. Module");
else if (func == FuncSetFailsafeExternalModule)
return tr("SetFailsafe Ext. Module");
return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafe)
return tr("Set Failsafe");
else if (func == FuncRangeCheckInternalModule)
return tr("RangeCheck Int. Module");
return tr("Range Check Int. Module");
else if (func == FuncRangeCheckExternalModule)
return tr("RangeCheck Ext. Module");
return tr("Range Check Ext. Module");
else if (func == FuncBindInternalModule)
return tr("Bind Int. Module");
else if (func == FuncBindExternalModule)
return tr("Bind Ext. Module");
else {
return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is)
return QString(CPN_STR_UNKNOWN_ITEM);
}
}
void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox * b, unsigned int value = 0)
{
int val = 0;
Firmware * firmware = Firmware::getCurrentVariant();
b->addItem(tr("Timer1"), val++);
b->addItem(tr("Timer2"), val++);
b->addItem( tr("Timer3"), val++);
b->addItem(tr("Flight"), val++);
b->addItem(tr("Telemetry"), val++);
int reCount = firmware->getCapability(RotaryEncoders);
if (reCount == 1) {
b->addItem(tr("Rotary Encoder"), val++);
}
else if (reCount == 2) {
b->addItem(tr("REa"), val++);
b->addItem(tr("REb"), val++);
}
if ((int)value < b->count()) {
b->setCurrentIndex(value);
}
if (model) {
for (unsigned i=0; i<CPN_MAX_SENSORS; ++i) {
if (model->sensorData[i].isAvailable()) {
RawSource item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i);
b->addItem(item.toString(model), val+i);
if (value == val+i) {
b->setCurrentIndex(b->count()-1);
}
}
}
}
}
void CustomFunctionData::populatePlaySoundParams(QStringList & qs)
{
qs <<"Beep 1" << "Beep 2" << "Beep 3" << "Warn1" << "Warn2" << "Cheep" << "Ratata" << "Tick" << "Siren" << "Ring" ;
qs << "SciFi" << "Robot" << "Chirp" << "Tada" << "Crickt" << "AlmClk" ;
}
void CustomFunctionData::populateHapticParams(QStringList & qs)
{
qs << "0" << "1" << "2" << "3";
}
QString CustomFunctionData::paramToString(const ModelData * model) const
{
QStringList qs;
if (func <= FuncInstantTrim) {
return QString("%1").arg(param);
}
else if (func==FuncLogs) {
return QString("%1").arg(param/10.0) + tr("s");
else if (func == FuncLogs) {
return QString("%1").arg(param / 10.0) + tr("s");
}
else if (func==FuncPlaySound) {
CustomFunctionData::populatePlaySoundParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
else if (func == FuncPlaySound) {
return playSoundToString(param);
}
else if (func==FuncPlayHaptic) {
CustomFunctionData::populateHapticParams(qs);
if (param>=0 && param<(int)qs.count())
return qs.at(param);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
else if (func == FuncPlayHaptic) {
return harpicToString(param);
}
else if (func==FuncReset) {
QComboBox cb;
CustomFunctionData::populateResetParams(model, &cb);
int pos = cb.findData(param);
if (pos >= 0)
return cb.itemText(pos);
else
return tr("<font color=red><b>Inconsistent parameter</b></font>");
else if (func == FuncReset) {
return resetToString(param, model);
}
else if ((func==FuncVolume)|| (func==FuncPlayValue)) {
RawSource item(param);
return item.toString(model);
else if (func == FuncVolume || func == FuncPlayValue || func == FuncBacklight) {
return RawSource(param).toString(model);
}
else if ((func==FuncPlayPrompt) || (func==FuncPlayBoth)) {
else if (func == FuncPlayPrompt || func == FuncPlayBoth) {
if ( getCurrentFirmware()->getCapability(VoicesAsNumbers)) {
return QString("%1").arg(param);
}
@@ -197,19 +153,17 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
return paramarm;
}
}
else if ((func>=FuncAdjustGV1) && (func<FuncCount)) {
else if (func >= FuncAdjustGV1 && func < FuncCount) {
switch (adjustMode) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value ")+QString("%1").arg(param);
return gvarAdjustModeToString(adjustMode) + QString(" %1").arg(param);
case FUNC_ADJUST_GVAR_SOURCE:
case FUNC_ADJUST_GVAR_GVAR:
return RawSource(param).toString();
case FUNC_ADJUST_GVAR_INCDEC:
float val;
QString unit;
val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return QString("Increment: %1%2").arg(val).arg(unit);
const float val = param * model->gvarData[func - FuncAdjustGV1].multiplierGet();
const QString unit = model->gvarData[func - FuncAdjustGV1].unitToString();
return gvarAdjustModeToString(adjustMode) + QString(": %1%2").arg(val).arg(unit);
}
}
return "";
@@ -217,25 +171,31 @@ QString CustomFunctionData::paramToString(const ModelData * model) const
QString CustomFunctionData::repeatToString() const
{
if (repeatParam == -1) {
return tr("played once, not during startup");
return repeatToString(repeatParam);
}
// static
QString CustomFunctionData::repeatToString(const int value)
{
if (value == -1) {
return tr("Played once, not during startup");
}
else if (repeatParam == 0) {
return "";
else if (value == 0) {
return tr("No repeat");
}
else {
unsigned int step = 1;
return tr("repeat(%1s)").arg(step*repeatParam);
return tr("Repeat %1s").arg(value);
}
}
QString CustomFunctionData::enabledToString() const
{
if ((func>=FuncOverrideCH1 && func<=FuncOverrideCH32) ||
(func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) ||
(func==FuncReset) ||
(func>=FuncSetTimer1 && func<=FuncSetTimer2) ||
(func==FuncVolume) ||
if ((func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) ||
(func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) ||
(func == FuncReset) ||
(func >= FuncSetTimer1 && func <= FuncSetTimerLast) ||
(func == FuncVolume) ||
(func == FuncBacklight) ||
(func <= FuncInstantTrim)) {
if (!enabled) {
return tr("DISABLED");
@@ -244,12 +204,197 @@ QString CustomFunctionData::enabledToString() const
return "";
}
void CustomFunctionData::convert(RadioDataConversionState & cstate)
// static
bool CustomFunctionData::isFuncAvailable(const int index)
{
cstate.setComponent(tr("CFN"), 8);
cstate.setSubComp(nameToString(cstate.subCompIdx, (cstate.toModel() ? false : true)));
swtch.convert(cstate);
if (func == FuncVolume || func == FuncPlayValue || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast && adjustMode == 1)) {
param = RawSource(param).convert(cstate.withComponentField("PARAM")).toValue();
Firmware * fw = getCurrentFirmware();
bool ret = (((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) && !fw->getCapability(SafetyChannelCustomFunction)) ||
((index == FuncVolume || index == FuncBackgroundMusic || index == FuncBackgroundMusicPause) && !fw->getCapability(HasVolume)) ||
((index == FuncPlayScript && !IS_HORUS_OR_TARANIS(fw->getBoard()))) ||
((index == FuncPlayHaptic) && !fw->getCapability(Haptic)) ||
((index == FuncPlayBoth) && !fw->getCapability(HasBeeper)) ||
((index == FuncLogs) && !fw->getCapability(HasSDLogs)) ||
((index >= FuncSetTimer1 && index <= FuncSetTimerLast) && index > FuncSetTimer1 + fw->getCapability(Timers)) ||
((index == FuncScreenshot) && !IS_HORUS_OR_TARANIS(fw->getBoard())) ||
((index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) && !fw->getCapability(DangerousFunctions)) ||
((index >= FuncAdjustGV1 && index <= FuncAdjustGVLast) && !fw->getCapability(Gvars))
);
return !ret;
}
// static
int CustomFunctionData::funcContext(const int index)
{
int ret = AllFunctionContexts;
if ((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) ||
(index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) ||
(index >= FuncAdjustGV1 && index <= FuncAdjustGVLast))
ret &= ~GlobalFunctionsContext;
return ret;
}
// static
QString CustomFunctionData::resetToString(const int value, const ModelData * model)
{
Firmware * firmware = getCurrentFirmware();
int step = CPN_MAX_TIMERS;
if (value < step) {
if (value < firmware->getCapability(Timers))
return RawSource(SOURCE_TYPE_SPECIAL, value + SOURCE_TYPE_SPECIAL_TIMER1_IDX).toString(model);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
if (value < ++step)
return tr("Flight");
if (value < ++step)
return tr("Telemetry");
if (value < step + firmware->getCapability(Sensors))
return RawSource(SOURCE_TYPE_TELEMETRY, 3 * (value - step)).toString(model);
return QString(CPN_STR_UNKNOWN_ITEM);
}
// static
int CustomFunctionData::resetParamCount()
{
Firmware * firmware = getCurrentFirmware();
return CPN_MAX_TIMERS + 2 + firmware->getCapability(Sensors);
}
// static
bool CustomFunctionData::isResetParamAvailable(const int index, const ModelData * model)
{
Firmware * firmware = getCurrentFirmware();
if (index < CPN_MAX_TIMERS) {
if (index < firmware->getCapability(Timers))
return true;
else
return false;
}
else if (index < CPN_MAX_TIMERS + 2)
return true;
else if (model && index < resetParamCount())
return model->sensorData[index - (CPN_MAX_TIMERS + 2)].isAvailable();
return false;
}
QString CustomFunctionData::harpicToString() const
{
return harpicToString(param);
}
// static
QString CustomFunctionData::harpicToString(const int value)
{
return QString("%1").arg(value);
}
// static
QStringList CustomFunctionData::playSoundStringList()
{
return QStringList({ tr("Beep 1"), tr("Beep 2"), tr("Beep 3"), tr("Warn 1"), tr("Warn 2"), tr("Cheep"), tr("Ratata"), tr("Tick"),
tr("Siren"), tr("Ring"), tr("Sci Fi"), tr("Robot"), tr("Chirp"), tr("Tada"), tr("Cricket"), tr("Alarm Clock") });
}
QString CustomFunctionData::playSoundToString() const
{
return playSoundToString(param);
}
// static
QString CustomFunctionData::playSoundToString(const int value)
{
const QStringList strl = playSoundStringList();
if (value < strl.count())
return strl.at(value);
else
return QString(CPN_STR_UNKNOWN_ITEM);
}
QString CustomFunctionData::gvarAdjustModeToString() const
{
return gvarAdjustModeToString(adjustMode);
}
// static
QString CustomFunctionData::gvarAdjustModeToString(const int value)
{
switch (value) {
case FUNC_ADJUST_GVAR_CONSTANT:
return tr("Value");
case FUNC_ADJUST_GVAR_SOURCE:
return tr("Source");
case FUNC_ADJUST_GVAR_GVAR:
return tr("Global Variable");
case FUNC_ADJUST_GVAR_INCDEC:
return tr("Inc/Decrement");
default:
return QString(CPN_STR_UNKNOWN_ITEM);
}
}
// static
AbstractStaticItemModel * CustomFunctionData::repeatItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.repeat");
for (int i = -1; i <= 60; i++) {
mdl->appendToItemList(repeatToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::playSoundItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.playsound");
for (int i = 0; i < playSoundStringList().count(); i++) {
mdl->appendToItemList(playSoundToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::harpicItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.harpic");
for (int i = 0; i <= 3; i++) {
mdl->appendToItemList(harpicToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * CustomFunctionData::gvarAdjustModeItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("customfunctiondata.gvaradjustmode");
for (int i = 0; i < FUNC_ADJUST_GVAR_COUNT; i++) {
mdl->appendToItemList(gvarAdjustModeToString(i), i);
}
mdl->loadItemList();
return mdl;
}
+47 -25
View File
@@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef CUSTOMFUNCTIONDATA_H
#define CUSTOMFUNCTIONDATA_H
#pragma once
#include "boards.h"
#include "constants.h"
@@ -32,10 +31,12 @@ class Firmware;
class ModelData;
class GeneralSettings;
class RadioDataConversionState;
class AbstractStaticItemModel;
enum AssignFunc {
FuncOverrideCH1 = 0,
FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1,
FuncOverrideCHLast = FuncOverrideCH1 + CPN_MAX_CHNOUT - 1,
FuncOverrideCH32 = FuncOverrideCHLast, // TODO remove
FuncTrainer,
FuncTrainerRUD,
FuncTrainerELE,
@@ -47,8 +48,9 @@ enum AssignFunc {
FuncPlayHaptic,
FuncReset,
FuncSetTimer1,
FuncSetTimer2,
FuncSetTimer3,
FuncSetTimer2, // TODO remove
FuncSetTimer3, // TODO remove
FuncSetTimerLast = FuncSetTimer1 + CPN_MAX_TIMERS - 1,
FuncVario,
FuncPlayPrompt,
FuncPlayBoth,
@@ -61,9 +63,8 @@ enum AssignFunc {
FuncBackgroundMusic,
FuncBackgroundMusicPause,
FuncAdjustGV1,
FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1,
FuncSetFailsafeInternalModule,
FuncSetFailsafeExternalModule,
FuncAdjustGVLast = FuncAdjustGV1 + CPN_MAX_GVARS - 1,
FuncSetFailsafe,
FuncRangeCheckInternalModule,
FuncRangeCheckExternalModule,
FuncBindInternalModule,
@@ -77,14 +78,23 @@ enum GVarAdjustModes
FUNC_ADJUST_GVAR_CONSTANT,
FUNC_ADJUST_GVAR_SOURCE,
FUNC_ADJUST_GVAR_GVAR,
FUNC_ADJUST_GVAR_INCDEC
FUNC_ADJUST_GVAR_INCDEC,
FUNC_ADJUST_GVAR_COUNT
};
class CustomFunctionData {
Q_DECLARE_TR_FUNCTIONS(CustomFunctionData)
public:
CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; }
enum CustomFunctionContext
{
GlobalFunctionsContext = 0x01,
SpecialFunctionsContext = 0x02,
AllFunctionContexts = GlobalFunctionsContext | SpecialFunctionsContext
};
CustomFunctionData(AssignFunc func = FuncOverrideCH1) { clear(); this->func = func; }
RawSwitch swtch;
AssignFunc func;
int param;
@@ -93,21 +103,33 @@ class CustomFunctionData {
unsigned int adjustMode;
int repeatParam;
void clear();
bool isEmpty() const;
QString nameToString(int index, bool globalContext = false) const;
QString funcToString(const ModelData * model = NULL) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value);
static void populatePlaySoundParams(QStringList & qs);
static void populateHapticParams(QStringList & qs);
void convert(RadioDataConversionState & cstate);
void clear();
bool isEmpty() const;
QString funcToString(const ModelData * model = nullptr) const;
QString paramToString(const ModelData * model = nullptr) const;
QString repeatToString() const;
QString enabledToString() const;
QString playSoundToString() const;
QString harpicToString() const;
QString gvarAdjustModeToString() const;
static QString nameToString(const int index, const bool globalContext = false);
static QString funcToString(const AssignFunc func, const ModelData * model = nullptr);
static bool isFuncAvailable(const int index);
static int funcContext(const int index);
static QString resetToString(const int value, const ModelData * model = nullptr);
static int resetParamCount();
static bool isResetParamAvailable(const int index, const ModelData * model = nullptr);
static QString repeatToString(const int value);
static QStringList playSoundStringList();
static QString playSoundToString(const int value);
static QString harpicToString(const int value);
static QStringList gvarAdjustModeStringList();
static QString gvarAdjustModeToString(const int value);
static AbstractStaticItemModel * repeatItemModel();
static AbstractStaticItemModel * playSoundItemModel();
static AbstractStaticItemModel * harpicItemModel();
static AbstractStaticItemModel * gvarAdjustModeItemModel();
};
#endif // CUSTOMFUNCTIONDATA_H
+70
View File
@@ -0,0 +1,70 @@
/*
* 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.
*/
#include "datahelpers.h"
QString DataHelpers::boolToString(const bool value, const BoolFormat format)
{
static const char *strings[] = {
QT_TRANSLATE_NOOP("DataHelpers", "Disabled"),
QT_TRANSLATE_NOOP("DataHelpers", "Enabled"),
QT_TRANSLATE_NOOP("DataHelpers", "OFF"),
QT_TRANSLATE_NOOP("DataHelpers", "ON"),
QT_TRANSLATE_NOOP("DataHelpers", "False"),
QT_TRANSLATE_NOOP("DataHelpers", "True"),
QT_TRANSLATE_NOOP("DataHelpers", "N"),
QT_TRANSLATE_NOOP("DataHelpers", "Y"),
QT_TRANSLATE_NOOP("DataHelpers", "No"),
QT_TRANSLATE_NOOP("DataHelpers", "Yes")
};
return QCoreApplication::translate("DataHelpers", strings[format * 2 + value]);
}
QString DataHelpers::getElementName(const QString & prefix, const unsigned int index, const char * name, const bool padding)
{
QString result = prefix;
result.append(padding ? QString("%1").arg(index, 2, 10, QChar('0')) : QString("%1").arg(index));
if (name && QString(name).trimmed().length() > 0)
result.append(":" + QString(name).trimmed());
return result;
}
QString DataHelpers::timeToString(const int value, const unsigned int mask)
{
bool negative = value < 0 ? true : false;
int val = abs(value);
QString result = QString("%1").arg(negative ? "-" : ((mask & TIMESTR_MASK_PADSIGN) ? " " : ""));
if (mask & TIMESTR_MASK_HRSMINS) {
int hours = val / 3600;
if (hours > 0 || (mask & TIMESTR_MASK_ZEROHRS)) {
val -= hours * 3600;
result.append(QString("%1:").arg(hours, 2, 10, QLatin1Char('0')));
}
}
int minutes = val / 60;
int seconds = val % 60;
result.append(QString("%1:%2").arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
return result;
}
+69
View File
@@ -0,0 +1,69 @@
/*
* 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.
*/
#pragma once
#include <QtCore>
class FieldRange
{
public:
FieldRange():
decimals(0),
min(0.0),
max(0.0),
step(1.0),
offset(0.0),
prefix(""),
unit("")
{
}
float getValue(int value) { return float(value) * step; }
int decimals;
double min;
double max;
double step;
double offset;
QString prefix;
QString unit;
};
constexpr unsigned int TIMESTR_MASK_HRSMINS { 1 << 1 };
constexpr unsigned int TIMESTR_MASK_ZEROHRS { 1 << 2 };
constexpr unsigned int TIMESTR_MASK_PADSIGN { 1 << 3 };
namespace DataHelpers
{
enum BoolFormat {
BOOL_FMT_ENABLEDISABLE,
BOOL_FMT_ONOFF,
BOOL_FMT_TRUEFALSE,
BOOL_FMT_YN,
BOOL_FMT_YESNO
};
QString boolToString(const bool value, const BoolFormat format);
QString getElementName(const QString & prefix, const unsigned int index, const char * name = 0, const bool padding = false);
QString timeToString(const int value, const unsigned int mask);
}
@@ -151,6 +151,7 @@ enum Capability {
DangerousFunctions,
HasModelCategories,
HasSwitchableJack,
HasSportConnector,
PwrButtonPress,
Sensors
};
@@ -18,121 +18,17 @@
* GNU General Public License for more details.
*/
#include "io_data.h"
#include "radiodata.h" // for RadioData::getElementName
#include "flightmodedata.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
/*
* ExpoData
*/
void ExpoData::convert(RadioDataConversionState & cstate)
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}
/*
* MixData
*/
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}
/*
* LimitData
*/
QString LimitData::minToString() const
{
return QString::number((qreal)min/10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max/10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset/10, 'f', 1);
}
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
return (min == -1000 && max == 1000 && !revert && !offset && !ppmCenter && !symetrical && name[0] == '\0' && !curve.isSet());
}
/*
* CurveData
*/
CurveData::CurveData()
{
clear();
}
void CurveData::clear(int count)
{
memset(this, 0, sizeof(CurveData));
this->count = count;
}
bool CurveData::isEmpty() const
{
for (int i=0; i<count; i++) {
if (points[i].y != 0) {
return false;
}
}
return true;
}
QString CurveData::nameToString(const int idx) const
{
return RadioData::getElementName(tr("CV"), idx + 1, name);
}
/*
* FlightModeData
*/
void FlightModeData::clear(const int phaseIdx)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(FlightModeData));
@@ -149,13 +45,6 @@ QString FlightModeData::nameToString(int phaseIdx) const
return RadioData::getElementName(tr("FM"), phaseIdx, name); // names are zero-based, FM0, FM1, etc
}
void FlightModeData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent("FMD", 2);
cstate.setSubComp(nameToString(cstate.subCompIdx));
swtch.convert(cstate);
}
bool FlightModeData::isEmpty(int phaseIdx) const
{
if (name[0] != '\0' || swtch.isSet() || fadeIn != 0 || fadeOut != 0)
+59
View File
@@ -0,0 +1,59 @@
/*
* 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.
*/
#pragma once
#include "constants.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN + 1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void convert(RadioDataConversionState & cstate);
void clear(const int phaseIdx);
bool isEmpty(int phaseIdx) const;
QString nameToString(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};
+14 -4
View File
@@ -94,6 +94,12 @@ GeneralSettings::GeneralSettings()
vBatMin = -23; // 6.7V
vBatMax = -37; // 8.3V
}
else if (IS_JUMPER_TLITE(board)) {
// 1S Li-Ion
vBatWarn = 32;
vBatMin = -60; //3V
vBatMax = -78; //4.2V
}
else if (IS_TARANIS(board)) {
// NI-MH 7.2V, X9D, X9D+ and X7
vBatWarn = 65;
@@ -239,6 +245,10 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
switchConfig[i] = Boards::getSwitchInfo(board, i).config;
}
// TLite does not have pots or sliders
if (IS_JUMPER_TLITE(board))
return;
// TODO: move to Boards, like with switches
if (IS_FAMILY_HORUS_OR_T16(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
@@ -253,11 +263,11 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITH_DETENT;
}
else if (IS_TARANIS(board)) {
else if (IS_FAMILY_T12(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_WITH_DETENT;
}
else if (IS_JUMPER_T12(board)) {
else if (IS_TARANIS(board)) {
potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_WITH_DETENT;
}
@@ -329,14 +339,14 @@ void GeneralSettings::convert(RadioDataConversionState & cstate)
}
}
if (IS_JUMPER_T12(cstate.toType)) {
if (IS_FAMILY_T12(cstate.toType)) {
if (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType)) {
strncpy(switchName[4], switchName[5], sizeof(switchName[0]));
strncpy(switchName[5], switchName[7], sizeof(switchName[0]));
}
}
else if (IS_JUMPER_T12(cstate.fromType)) {
else if (IS_FAMILY_T12(cstate.fromType)) {
if (IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) {
strncpy(switchName[5], switchName[4], sizeof(switchName[0]));
strncpy(switchName[7], switchName[5], sizeof(switchName[0]));
@@ -103,6 +103,7 @@ class GeneralSettings {
bool disableRssiPoweroffAlarm;
unsigned int usbMode;
unsigned int jackMode;
bool sportPower;
BeeperMode hapticMode;
unsigned int stickMode; // TODO enum
int timezone;
+21
View File
@@ -0,0 +1,21 @@
/*
* 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.
*/
#include "heli_data.h"
+44
View File
@@ -0,0 +1,44 @@
/*
* 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.
*/
#pragma once
#include "rawsource.h"
#include <QtCore>
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};
+35
View File
@@ -0,0 +1,35 @@
/*
* 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.
*/
#include "input_data.h"
#include "radiodataconversionstate.h"
void ExpoData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("INP"), 3);
cstate.setSubComp(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, chn).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool ExpoData::isEmpty() const
{
return (chn == 0 && mode == INPUT_MODE_NONE);
}
+61
View File
@@ -0,0 +1,61 @@
/*
* 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.
*/
#pragma once
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
bool isEmpty() const;
};
-199
View File
@@ -1,199 +0,0 @@
/*
* 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 IO_DATA_H
#define IO_DATA_H
#include "constants.h"
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum InputMode {
INPUT_MODE_NONE,
INPUT_MODE_POS,
INPUT_MODE_NEG,
INPUT_MODE_BOTH
};
#define EXPODATA_NAME_LEN 10
class ExpoData {
Q_DECLARE_TR_FUNCTIONS(ExpoData)
public:
ExpoData() { clear(); }
RawSource srcRaw;
unsigned int scale;
unsigned int mode; // InputMode
unsigned int chn;
RawSwitch swtch;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int weight;
int offset;
CurveReference curve;
int carryTrim;
char name[EXPODATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(ExpoData)); }
void convert(RadioDataConversionState & cstate);
bool isEmpty() const;
};
enum MltpxValue {
MLTPX_ADD=0,
MLTPX_MUL=1,
MLTPX_REP=2
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
void convert(RadioDataConversionState & cstate);
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve; //0=symmetrisch
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp; // Servogeschwindigkeit aus Tabelle (10ms Cycle)
unsigned int speedDown; // 0 nichts
int carryTrim;
bool noExpo;
MltpxValue mltpx; // multiplex method 0=+ 1=* 2=replace
unsigned int mixWarn; // mixer warning
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN+1];
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
void clear();
bool isEmpty() const;
};
class CurvePoint {
public:
int8_t x;
int8_t y;
};
#define CURVEDATA_NAME_LEN 6
class CurveData {
Q_DECLARE_TR_FUNCTIONS(CurveData)
public:
enum CurveType {
CURVE_TYPE_STANDARD,
CURVE_TYPE_CUSTOM,
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
CurveData();
void clear(int count = 5);
bool isEmpty() const;
QString nameToString(const int idx) const;
CurveType type;
bool smooth;
int count;
CurvePoint points[CPN_MAX_POINTS];
char name[CURVEDATA_NAME_LEN+1];
};
#define FLIGHTMODE_NAME_LEN 10
#define RENC_MAX_VALUE 1024
#define RENC_MIN_VALUE -RENC_MAX_VALUE
class FlightModeData {
Q_DECLARE_TR_FUNCTIONS(FlightModeData)
public:
FlightModeData() { clear(0); }
int trimMode[CPN_MAX_TRIMS];
int trimRef[CPN_MAX_TRIMS];
int trim[CPN_MAX_TRIMS];
RawSwitch swtch;
char name[FLIGHTMODE_NAME_LEN+1];
unsigned int fadeIn;
unsigned int fadeOut;
int rotaryEncoders[CPN_MAX_ENCODERS];
int gvars[CPN_MAX_GVARS];
void clear(const int phaseIdx);
QString nameToString(int phaseIdx) const;
void convert(RadioDataConversionState & cstate);
bool isEmpty(int phaseIdx) const;
bool isGVarEmpty(int phaseIdx, int gvIdx) const;
bool isREncEmpty(int phaseIdx, int reIdx) const;
int linkedFlightModeZero(int phaseIdx, int maxOwnValue) const;
int linkedGVarFlightModeZero(int phaseIdx) const;
int linkedREncFlightModeZero(int phaseIdx) const;
};
class SwashRingData {
Q_DECLARE_TR_FUNCTIONS(SwashRingData)
public:
SwashRingData() { clear(); }
int elevatorWeight;
int aileronWeight;
int collectiveWeight;
unsigned int type;
RawSource collectiveSource;
RawSource aileronSource;
RawSource elevatorSource;
unsigned int value;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(SwashRingData)); }
};
#endif // IO_DATA_H
+35
View File
@@ -0,0 +1,35 @@
/*
* 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.
*/
#include "mixdata.h"
#include "radiodataconversionstate.h"
void MixData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("MIX"), 4);
cstate.setSubComp(RawSource(SOURCE_TYPE_CH, destCh-1).toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType) % tr(" (@%1)").arg(cstate.subCompIdx));
srcRaw.convert(cstate);
swtch.convert(cstate);
}
bool MixData::isEmpty() const
{
return (destCh == 0);
}
+65
View File
@@ -0,0 +1,65 @@
/*
* 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.
*/
#pragma once
#include "curvereference.h"
#include "rawsource.h"
#include "rawswitch.h"
#include <QtCore>
class RadioDataConversionState;
enum MltpxValue {
MLTPX_ADD,
MLTPX_MUL,
MLTPX_REP
};
#define MIXDATA_NAME_LEN 10
class MixData {
Q_DECLARE_TR_FUNCTIONS(MixData)
public:
MixData() { clear(); }
unsigned int destCh; // 1..CPN_MAX_CHNOUT
RawSource srcRaw;
int weight;
RawSwitch swtch;
CurveReference curve;
unsigned int delayUp;
unsigned int delayDown;
unsigned int speedUp;
unsigned int speedDown;
int carryTrim;
bool noExpo;
MltpxValue mltpx;
unsigned int mixWarn;
unsigned int flightModes; // -5=!FP4, 0=normal, 5=FP4
int sOffset;
char name[MIXDATA_NAME_LEN + 1];
void convert(RadioDataConversionState & cstate);
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(MixData)); }
bool isEmpty() const;
};
+320 -59
View File
@@ -27,26 +27,6 @@
#include "helpers.h"
#include "adjustmentreference.h"
/*
* TimerData
*/
void TimerData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("TMR"), 1);
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
mode.convert(cstate);
}
bool TimerData::isEmpty()
{
return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWN_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/);
}
/*
* ModelData
*/
ModelData::ModelData()
{
clear();
@@ -527,6 +507,8 @@ int ModelData::updateReference()
Firmware *fw = getCurrentFirmware();
updRefInfo.occurences = 1;
switch (updRefInfo.type)
{
case REF_UPD_TYPE_CHANNEL:
@@ -561,6 +543,7 @@ int ModelData::updateReference()
updRefInfo.srcType = SOURCE_TYPE_TELEMETRY;
updRefInfo.swtchType = SWITCH_TYPE_SENSOR;
updRefInfo.maxindex = fw->getCapability(Sensors);
updRefInfo.occurences = 3;
break;
case REF_UPD_TYPE_TIMER:
updRefInfo.srcType = SOURCE_TYPE_SPECIAL;
@@ -651,6 +634,8 @@ int ModelData::updateReference()
}
}
}
if (updRefInfo.type == REF_UPD_TYPE_CHANNEL)
sortMixes();
//s1.report("Mixes");
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
@@ -668,41 +653,56 @@ int ModelData::updateReference()
LogicalSwitchData *lsd = &logicalSw[i];
if (!lsd->isEmpty()) {
bool clearlsd = false;
int oldval1;
int oldval2;
CSFunctionFamily family = lsd->getFunctionFamily();
switch(family) {
case LS_FAMILY_VOFS:
updateSourceIntRef(lsd->val1);
if (lsd->val1 == 0)
clearlsd = true;
if (lsd->val1 != 0) {
updateSourceIntRef(lsd->val1);
if (lsd->val1 == 0)
clearlsd = true;
}
break;
case LS_FAMILY_STICKY:
case LS_FAMILY_VBOOL:
updateSwitchIntRef(lsd->val1);
updateSwitchIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0)
oldval1 = lsd->val1;
oldval2 = lsd->val2;
if (lsd->val1 != 0)
updateSwitchIntRef(lsd->val1);
if (lsd->val2 != 0)
updateSwitchIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0 && ((lsd->val1 != oldval1 && oldval2 == 0) || (lsd->val2 != oldval2 && oldval1 == 0)))
clearlsd = true;
break;
case LS_FAMILY_EDGE:
updateSwitchIntRef(lsd->val1);
if (lsd->val1 == 0)
clearlsd = true;
if (lsd->val1 != 0) {
updateSwitchIntRef(lsd->val1);
if (lsd->val1 == 0)
clearlsd = true;
}
break;
case LS_FAMILY_VCOMP:
updateSourceIntRef(lsd->val1);
updateSourceIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0)
oldval1 = lsd->val1;
oldval2 = lsd->val2;
if (lsd->val1 != 0)
updateSourceIntRef(lsd->val1);
if (lsd->val2 != 0)
updateSourceIntRef(lsd->val2);
if (lsd->val1 == 0 && lsd->val2 == 0 && ((lsd->val1 != oldval1 && oldval2 == 0) || (lsd->val2 != oldval2 && oldval1 == 0)))
clearlsd = true;
break;
default:
break;
}
if (clearlsd) {
if (lsd->andsw != 0)
updateSwitchIntRef(lsd->andsw);
if (clearlsd && lsd->andsw == 0) {
lsd->clear();
appendUpdateReferenceParams(REF_UPD_TYPE_LOGICAL_SWITCH, REF_UPD_ACT_CLEAR, i);
}
else {
updateSwitchIntRef(lsd->andsw);
}
}
}
//s1.report("Logical Switches");
@@ -713,11 +713,15 @@ int ModelData::updateReference()
updateAssignFunc(cfd);
if (!cfd->isEmpty()) {
updateSwitchRef(cfd->swtch);
if (cfd->func == FuncVolume || cfd->func == FuncPlayValue || (cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) {
if (cfd->func == FuncVolume || cfd->func == FuncBacklight || cfd->func == FuncPlayValue ||
(cfd->func >= FuncAdjustGV1 && cfd->func <= FuncAdjustGVLast && (cfd->adjustMode == FUNC_ADJUST_GVAR_GVAR || cfd->adjustMode == FUNC_ADJUST_GVAR_SOURCE))) {
updateSourceIntRef(cfd->param);
if (cfd->param == 0)
cfd->clear();
}
else if (cfd->func == FuncReset) {
updateResetParam(cfd);
}
}
}
}
@@ -762,15 +766,35 @@ int ModelData::updateReference()
//s1.report("Telemetry");
}
// TODO maybe less risk to leave it up to the user??
/*
for (int i = 0; i < CPN_MAX_SENSORS; i++) {
SensorData *sd = &sensorData[i];
if (sd->isAvailable() && sd->type == SensorData::TELEM_TYPE_CALCULATED) {
if (!sd->isEmpty() && sd->type == SensorData::TELEM_TYPE_CALCULATED) {
if (sd->formula == SensorData::TELEM_FORMULA_CELL) {
updateTelemetryRef(sd->source);
if (sd->source == 0) {
sd->clear();
appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i);
}
}
else if (sd->formula == SensorData::TELEM_FORMULA_DIST) {
updateTelemetryRef(sd->gps);
updateTelemetryRef(sd->alt);
}
else if (sd->formula == SensorData::TELEM_FORMULA_CONSUMPTION || sd->formula == SensorData::TELEM_FORMULA_TOTALIZE) {
updateTelemetryRef(sd->amps);
if (sd->amps == 0) {
sd->clear();
appendUpdateReferenceParams(REF_UPD_TYPE_SENSOR, REF_UPD_ACT_CLEAR, i);
}
}
else {
for (unsigned int i = 0; i < 4; i++) {
updateTelemetryRef(sd->sources[i]);
}
}
}
}
s1.report("Telemetry Sensors");
*/
//s1.report("Telemetry Sensors");
// TODO needs lua incorporated into Companion as script needs to be parsed to determine if input field is source or value
/*
@@ -806,10 +830,13 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
newRef.type = curRef.type;
newRef.index = abs(curRef.index);
div_t idx = div(newRef.index, updRefInfo.occurences);
div_t newidx;
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
if (newRef.index != (updRefInfo.index1 + idxAdj))
if (idx.quot != (updRefInfo.index1 + idxAdj))
return;
if (defClear)
newRef.clear();
@@ -819,25 +846,26 @@ void ModelData::updateTypeIndexRef(R & curRef, const T type, const int idxAdj, c
}
break;
case REF_UPD_ACT_SHIFT:
if (newRef.index < (updRefInfo.index1 + idxAdj))
if (idx.quot < (updRefInfo.index1 + idxAdj))
return;
newRef.index += updRefInfo.shift;
newRef.index = ((idx.quot + updRefInfo.shift) * updRefInfo.occurences) + idx.rem;
newidx = div(newRef.index, updRefInfo.occurences);
if (newRef.index < (updRefInfo.index1 + idxAdj) || newRef.index > (updRefInfo.maxindex + idxAdj)) {
if (newidx.quot < (updRefInfo.index1 + idxAdj) || newidx.quot > (updRefInfo.maxindex + idxAdj)) {
if (defClear)
newRef.clear();
else {
newRef.type = (T)defType;
newRef.index = defIndex;
newRef.index = defIndex + idxAdj;
}
}
break;
case REF_UPD_ACT_SWAP:
if (newRef.index == updRefInfo.index1 + idxAdj)
newRef.index = updRefInfo.index2 + idxAdj;
else if (newRef.index == updRefInfo.index2 + idxAdj)
newRef.index = updRefInfo.index1 + idxAdj;
if (idx.quot == updRefInfo.index1 + idxAdj)
newRef.index = ((updRefInfo.index2 + idxAdj) * updRefInfo.occurences) + idx.rem;
else if (idx.quot == updRefInfo.index2 + idxAdj)
newRef.index = ((updRefInfo.index1 + idxAdj) * updRefInfo.occurences) + idx.rem;
break;
default:
qDebug() << "Error - unhandled action:" << updRefInfo.action;
@@ -886,7 +914,7 @@ void ModelData::updateTypeValueRef(R & curRef, const T type, const int idxAdj, c
newRef.clear();
else {
newRef.type = (T)defType;
newRef.value = defValue;
newRef.value = defValue + idxAdj;
}
}
break;
@@ -940,7 +968,7 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd)
{
const int invalidateRef = -1;
int newRef = (int)cfd->func;
int idxAdj;
int idxAdj = 0;
switch (updRefInfo.type)
{
@@ -957,7 +985,7 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd)
case REF_UPD_TYPE_TIMER:
if (cfd->func < FuncSetTimer1 || cfd->func > FuncSetTimer3) // TODO refactor to FuncSetTimerLast
return;
idxAdj = FuncSetTimer1 - 2; // reverse earlier offset requiured for rawsource
idxAdj = FuncSetTimer1 - 2; // reverse earlier offset required for rawsource
break;
default:
return;
@@ -1070,7 +1098,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
flag[updRefInfo.index1] = false;
flag[updRefInfo.index1] = true;
break;
case REF_UPD_ACT_SHIFT:
if(updRefInfo.shift < 0) {
@@ -1078,7 +1106,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
if (i - updRefInfo.shift <= updRefInfo.maxindex)
flag[i] = flag[i - updRefInfo.shift];
else
flag[i] = false;
flag[i] = true;
}
}
else {
@@ -1086,7 +1114,7 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
if (i - updRefInfo.shift >= updRefInfo.index1)
flag[i] = flag[i - updRefInfo.shift];
else
flag[i] = false;
flag[i] = true;
}
}
break;
@@ -1115,13 +1143,14 @@ void ModelData::updateFlightModeFlags(unsigned int & curRef)
}
}
void ModelData::updateTelemetryRef(unsigned int & curRef)
void ModelData::updateTelemetryRef(int & curRef)
{
if (updRefInfo.type != REF_UPD_TYPE_SENSOR)
return;
const int idxAdj = 1;
int newRef = curRef;
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
@@ -1149,13 +1178,23 @@ void ModelData::updateTelemetryRef(unsigned int & curRef)
return;
}
if (curRef != static_cast<unsigned int>(newRef)) {
if (curRef != newRef) {
//qDebug() << "Updated reference:" << curRef << " -> " << newRef;
curRef = newRef;
updRefInfo.updcnt++;
}
}
void ModelData::updateTelemetryRef(unsigned int & curRef)
{
int newRef = (int)curRef;
updateTelemetryRef(newRef);
if (curRef != static_cast<unsigned int>(newRef)) {
curRef = (unsigned int)newRef;
}
}
void ModelData::updateModuleFailsafes(ModuleData * md)
{
if (updRefInfo.type != REF_UPD_TYPE_CHANNEL)
@@ -1289,3 +1328,225 @@ void ModelData::removeMix(const int idx)
memmove(&mixData[idx], &mixData[idx + 1], (CPN_MAX_MIXERS - (idx + 1)) * sizeof(MixData));
mixData[CPN_MAX_MIXERS - 1].clear();
}
void ModelData::sortMixes()
{
unsigned int lastchn = 0;
bool sortreq = false;
for (int i = 0; i < CPN_MAX_MIXERS; i++) {
MixData *md = &mixData[i];
if (!md->isEmpty()) {
if (md->destCh < lastchn) {
sortreq = true;
break;
}
else
lastchn = md->destCh;
}
}
if (!sortreq)
return;
// QMap automatically sorts based on key
QMap<int, int> map;
for (int i = 0; i < CPN_MAX_MIXERS; i++) {
MixData *md = &mixData[i];
if (!md->isEmpty()) {
// destCh may not be unique so build a compound sort key
map.insert(md->destCh * (CPN_MAX_MIXERS + 1) + i, i);
}
}
MixData sortedMixData[CPN_MAX_MIXERS];
int destidx = 0;
QMap<int, int>::const_iterator i;
for (i = map.constBegin(); i != map.constEnd(); ++i) {
memcpy(&sortedMixData[destidx], &mixData[i.value()], sizeof(MixData));
destidx++;
}
memcpy(&mixData[0], &sortedMixData[0], CPN_MAX_MIXERS * sizeof(MixData));
}
void ModelData::updateResetParam(CustomFunctionData * cfd)
{
if (cfd->func != FuncReset)
return;
const int invalidateRef = -1;
int newRef = cfd->param;
int idxAdj = 0;
Firmware *firmware = getCurrentFirmware();
switch (updRefInfo.type)
{
case REF_UPD_TYPE_TIMER:
if (cfd->param < 0 || cfd->param > 2)
return;
idxAdj = -2; // reverse earlier offset required for rawsource
break;
case REF_UPD_TYPE_SENSOR:
idxAdj = 5/*3 Timers + Flight + Telemetery*/ + firmware->getCapability(RotaryEncoders);
if (cfd->param < idxAdj || cfd->param > (idxAdj + firmware->getCapability(Sensors)))
return;
break;
default:
return;
}
switch (updRefInfo.action)
{
case REF_UPD_ACT_CLEAR:
if (newRef != (updRefInfo.index1 + idxAdj))
return;
newRef = invalidateRef;
break;
case REF_UPD_ACT_SHIFT:
if (newRef < (updRefInfo.index1 + idxAdj))
return;
newRef += updRefInfo.shift;
if (newRef < (updRefInfo.index1 + idxAdj) || newRef > (updRefInfo.maxindex + idxAdj))
newRef = invalidateRef;
break;
case REF_UPD_ACT_SWAP:
if (newRef == updRefInfo.index1 + idxAdj)
newRef = updRefInfo.index2 + idxAdj;
else if (newRef == updRefInfo.index2 + idxAdj)
newRef = updRefInfo.index1 + idxAdj;
break;
default:
qDebug() << "Error - unhandled action:" << updRefInfo.action;
return;
}
if (newRef == invalidateRef) {
cfd->clear();
//qDebug() << "Function cleared";
updRefInfo.updcnt++;
}
else if (cfd->param != newRef) {
//qDebug() << "Updated reference:" << cfd->param << " -> " << newRef;
cfd->param = newRef;
updRefInfo.updcnt++;
}
}
QString ModelData::thrTraceSrcToString() const
{
return thrTraceSrcToString((int)thrTraceSrc);
}
QString ModelData::thrTraceSrcToString(const int index) const
{
Firmware * firmware = getCurrentFirmware();
const Boards board = Boards(getCurrentBoard());
const int pscnt = board.getCapability(Board::Pots) + board.getCapability(Board::Sliders);
if (index == 0)
return tr("THR");
else if (index <= pscnt)
return board.getAnalogInputName(index + board.getCapability(Board::Sticks) - 1);
else if (index <= pscnt + firmware->getCapability(Outputs))
return RawSource(SOURCE_TYPE_CH, index - pscnt - 1).toString(this);
return QString(CPN_STR_UNKNOWN_ITEM);
}
int ModelData::thrTraceSrcCount() const
{
const Boards board = Boards(getCurrentBoard());
Firmware * firmware = getCurrentFirmware();
return 1 + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + firmware->getCapability(Outputs);
}
bool ModelData::isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const
{
const Boards board = Boards(getCurrentBoard());
if (index > 0 && index <= board.getCapability(Board::Pots) + board.getCapability(Board::Sliders))
return RawSource(SOURCE_TYPE_STICK, index + board.getCapability(Board::Sticks) - 1).isAvailable(this, generalSettings, board.getBoardType());
else
return true;
}
void ModelData::limitsClear(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
if (!limitData[index].isEmpty()) {
limitData[index].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_CLEAR, index);
}
}
void ModelData::limitsClearAll()
{
for (int i = 0; i < CPN_MAX_CHNOUT; i++) {
limitsClear(i);
}
}
void ModelData::limitsDelete(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
memmove(&limitData[index], &limitData[index + 1], (CPN_MAX_CHNOUT - (index + 1)) * sizeof(LimitData));
limitData[CPN_MAX_CHNOUT - 1].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SHIFT, index, 0, -1);
}
void ModelData::limitsGet(const int index, QByteArray & data)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
data.append((char*)&limitData[index], sizeof(LimitData));
}
void ModelData::limitsInsert(const int index)
{
if (index < 0 || index >= CPN_MAX_CHNOUT)
return;
memmove(&limitData[index + 1], &limitData[index], (CPN_MAX_CHNOUT - (index + 1)) * sizeof(LimitData));
limitData[index].clear();
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SHIFT, index, 0, 1);
}
void ModelData::limitsMove(const int index, const int offset)
{
if (index + offset < 0 || index + offset >= CPN_MAX_CHNOUT)
return;
int idx1 = index;
int idx2;
const int direction = offset < 0 ? -1 : 1;
const int cnt = abs(offset);
for (int i = 1; i <= cnt; i++) {
idx2 = idx1 + direction;
LimitData tmp = limitData[idx2];
LimitData *d1 = &limitData[idx1];
LimitData *d2 = &limitData[idx2];
memcpy(d2, d1, sizeof(LimitData));
memcpy(d1, &tmp, sizeof(LimitData));
updateAllReferences(REF_UPD_TYPE_CHANNEL, REF_UPD_ACT_SWAP, idx1, idx2);
idx1 += direction;
}
}
void ModelData::limitsSet(const int index, const QByteArray & data)
{
if (index < 0 || index >= CPN_MAX_CHNOUT || data.size() < (int)sizeof(LimitData))
return;
memcpy(&limitData[index], data.constData(), sizeof(LimitData));
}
+25 -31
View File
@@ -18,17 +18,22 @@
* GNU General Public License for more details.
*/
#ifndef MODELDATA_H
#define MODELDATA_H
#pragma once
#include "constants.h"
#include "curvedata.h"
#include "customfunctiondata.h"
#include "gvardata.h"
#include "io_data.h"
#include "flightmodedata.h"
#include "heli_data.h"
#include "input_data.h"
#include "logicalswitchdata.h"
#include "mixdata.h"
#include "moduledata.h"
#include "output_data.h"
#include "sensordata.h"
#include "telem_data.h"
#include "timerdata.h"
#include <QtCore>
@@ -51,32 +56,6 @@ class RSSIAlarmData {
}
};
#define TIMER_NAME_LEN 8
class TimerData {
Q_DECLARE_TR_FUNCTIONS(TimerData)
public:
enum CountDownMode {
COUNTDOWN_SILENT,
COUNTDOWN_BEEPS,
COUNTDOWN_VOICE,
COUNTDOWN_HAPTIC
};
TimerData() { clear(); }
RawSwitch mode;
char name[TIMER_NAME_LEN+1];
bool minuteBeep;
unsigned int countdownBeep;
unsigned int val;
unsigned int persistent;
int pvalue;
void clear() { memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData)); mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
void convert(RadioDataConversionState & cstate);
bool isEmpty();
bool isModeOff() { return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0); }
};
#define CPN_MAX_SCRIPTS 9
#define CPN_MAX_SCRIPT_INPUTS 10
class ScriptData {
@@ -181,6 +160,7 @@ class ModelData {
unsigned int thrTraceSrc;
uint64_t switchWarningStates;
unsigned int switchWarningEnable;
unsigned int thrTrimSwitch;
unsigned int potsWarningMode;
bool potsWarnEnabled[CPN_MAX_POTS];
int potsWarnPosition[CPN_MAX_POTS];
@@ -281,6 +261,18 @@ class ModelData {
bool hasExpoChildren(const int index);
bool hasExpoSiblings(const int index);
void removeMix(const int idx);
QString thrTraceSrcToString() const;
QString thrTraceSrcToString(const int index) const;
int thrTraceSrcCount() const;
bool isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const;
void limitsClear(const int index);
void limitsClearAll();
void limitsDelete(const int index);
void limitsGet(const int index, QByteArray & data);
void limitsInsert(const int index);
void limitsMove(const int index, const int offset);
void limitsSet(const int index, const QByteArray & data);
protected:
void removeGlobalVar(int & var);
@@ -297,6 +289,7 @@ class ModelData {
int shift;
int updcnt;
int maxindex;
int occurences;
RawSourceType srcType;
RawSwitchType swtchType;
};
@@ -314,6 +307,7 @@ class ModelData {
void updateDestCh(MixData * md);
void updateLimitCurveRef(CurveReference & crv);
void updateFlightModeFlags(unsigned int & flags);
void updateTelemetryRef(int & idx);
void updateTelemetryRef(unsigned int & idx);
void updateModuleFailsafes(ModuleData * md);
inline void updateSourceRef(RawSource & src) { updateTypeIndexRef<RawSource, RawSourceType>(src, updRefInfo.srcType); }
@@ -333,6 +327,6 @@ class ModelData {
if (value != swtch.toValue())
value = swtch.toValue();
}
void sortMixes();
void updateResetParam(CustomFunctionData * cfd);
};
#endif // MODELDATA_H
+4 -14
View File
@@ -45,19 +45,6 @@ bool ModuleData::isPxx2Module() const
}
}
bool ModuleData::isPxx1Module() const
{
switch(protocol){
case PULSES_PXX_XJT_X16:
case PULSES_PXX_R9M:
case PULSES_PXX_R9M_LITE:
case PULSES_PXX_R9M_LITE_PRO:
return true;
default:
return false;
}
}
bool ModuleData::supportRxNum() const
{
switch (protocol) {
@@ -66,6 +53,7 @@ bool ModuleData::supportRxNum() const
case PULSES_PXX_R9M_LITE:
case PULSES_PXX_R9M_LITE_PRO:
case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE:
case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16:
case PULSES_ACCESS_R9M:
@@ -160,7 +148,8 @@ QString ModuleData::protocolToString(unsigned protocol)
"FrSky ACCESS R9M Lite",
"FrSky ACCESS R9M Lite Pro",
"FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)",
"AFHDS3"
"AFHDS3",
"ImmersionRC Ghost"
};
return CHECK_IN_ARRAY(strings, protocol);
@@ -221,6 +210,7 @@ int ModuleData::getMaxChannelCount()
case PULSES_XJT_LITE_X16:
case PULSES_PXX_XJT_X16:
case PULSES_CROSSFIRE:
case PULSES_GHOST:
case PULSES_SBUS:
case PULSES_PPM:
return 16;
+13 -4
View File
@@ -59,6 +59,7 @@ enum PulsesProtocol {
PULSES_XJT_LITE_D8,
PULSES_XJT_LITE_LR12,
PULSES_AFHDS3,
PULSES_GHOST,
PULSES_PROTOCOL_LAST
};
@@ -83,7 +84,7 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_MJXQ,
MODULE_SUBTYPE_MULTI_SHENQI,
MODULE_SUBTYPE_MULTI_FY326,
MODULE_SUBTYPE_MULTI_SFHSS,
MODULE_SUBTYPE_MULTI_FUTABA,
MODULE_SUBTYPE_MULTI_J6PRO,
MODULE_SUBTYPE_MULTI_FQ777,
MODULE_SUBTYPE_MULTI_ASSAN,
@@ -114,7 +115,7 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_REDPINE,
MODULE_SUBTYPE_MULTI_POTENSIC,
MODULE_SUBTYPE_MULTI_ZSX,
MODULE_SUBTYPE_MULTI_FLYZONE,
MODULE_SUBTYPE_MULTI_HEIGHT,
MODULE_SUBTYPE_MULTI_SCANNER,
MODULE_SUBTYPE_MULTI_FRSKYX_RX,
MODULE_SUBTYPE_MULTI_AFHDS2A_RX,
@@ -134,7 +135,15 @@ enum MultiModuleRFProtocols {
MODULE_SUBTYPE_MULTI_DSM_RX,
MODULE_SUBTYPE_MULTI_JJRC345,
MODULE_SUBTYPE_MULTI_Q90C,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_Q90C
MODULE_SUBTYPE_MULTI_KYOSHO,
MODULE_SUBTYPE_MULTI_RLINK,
MODULE_SUBTYPE_MULTI_ELRS,
MODULE_SUBTYPE_MULTI_REALACC,
MODULE_SUBTYPE_MULTI_OMP,
MODULE_SUBTYPE_MULTI_MLINK,
MODULE_SUBTYPE_MULTI_WFLY2,
MODULE_SUBTYPE_MULTI_E016HV2,
MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2
};
enum TrainerProtocol {
@@ -206,12 +215,12 @@ class ModuleData {
struct Access {
unsigned int receivers;
char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME+1];
unsigned int racingMode;
} access;
void clear() { memset(this, 0, sizeof(ModuleData)); }
void convert(RadioDataConversionState & cstate);
bool isPxx2Module() const;
bool isPxx1Module() const;
bool supportRxNum() const;
QString polarityToString() const { return ppm.pulsePol ? tr("Positive") : tr("Negative"); }
QString rfProtocolToString() const;
+29 -13
View File
@@ -55,8 +55,9 @@ static const QStringList STR_SUBTYPE_ESky {"Standard", "ET4"};
static const QStringList STR_SUBTYPE_MT99 {"MT99", "H7", "YZ", "LS", "FY805"};
static const QStringList STR_SUBTYPE_MJXQ {"WLH08", "X600", "X800", "H26D", "E010", "H26WH", "Phoenix"};
static const QStringList STR_SUBTYPE_FY326 {"Standard", "FY319"};
static const QStringList STR_SUBTYPE_FUTABA {"SFHSS"};
static const QStringList STR_SUBTYPE_HONTAI {"Standard", "JJRC X1", "X5C1 Clone", "FQ777_951"};
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS"};
static const QStringList STR_SUBTYPE_AFHDS2A {"PWM and IBUS", "PPM and IBUS", "PWM and SBUS", "PPM and SBUS", "PWM and IBUS16", "PPM and IBUS16"};
static const QStringList STR_SUBTYPE_Q2X2 {"Q222", "Q242", "Q282"};
static const QStringList STR_SUBTYPE_WK2x01 {"WK2801", "WK2401", "W6_5_1", "W6_6_1", "W6_HEL", "W6_HEL_I"};
static const QStringList STR_SUBTYPE_Q303 {"Standard", "CX35", "CX10D", "CX10WD"};
@@ -65,7 +66,7 @@ static const QStringList STR_SUBTYPE_ESKY150 {"4 Channel", "7 Channel"};
static const QStringList STR_SUBTYPE_H83D {"H8 Mini 3D", "H20H", "H20 Mini", "H30 Mini"};
static const QStringList STR_SUBTYPE_CORONA {"Corona V1", "Corona V2", "Flydream V3"};
static const QStringList STR_SUBTYPE_HITEC {"Optima", "Optima Hub Telem", "Minima"};
static const QStringList STR_SUBTYPE_WFLY {"WFR0xS"};
static const QStringList STR_SUBTYPE_WFLY {"WFR0x"};
static const QStringList STR_SUBTYPE_BUGS_MINI {"Standard", "Bugs 3H"};
static const QStringList STR_SUBTYPE_TRAXXAS {"6519 RX"};
static const QStringList STR_SUBTYPE_E01X {"E012", "E015", "E016H"};
@@ -75,18 +76,24 @@ static const QStringList STR_SUBTYPE_V761 {"3 Channel", "4 Channel"};
static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"};
static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"};
static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"};
static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"};
static const QStringList STR_SUBTYPE_HEIGHT {"5 Channel", "8 Channel"};
static const QStringList STR_SUBTYPE_FRSKYX_RX {"RX", "Clone TX"};
static const QStringList STR_SUBTYPE_HOTT {"Sync", "No_Sync"};
static const QStringList STR_SUBTYPE_FX816 {"P38"};
static const QStringList STR_SUBTYPE_PELIKAN {"Pro", "Lite"};
static const QStringList STR_SUBTYPE_XK {"X450", "X420"};
static const QStringList STR_SUBTYPE_XN297DUMP {"250K", "1M", "2M", "AUTO", "NRF"};
static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "D16 Cloned"};
static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel"};
static const QStringList STR_SUBTYPE_FRSKYX2 {"D16", "D16 8ch", "D16 EU-LBT", "D16 EU-LBT 8ch", "Cloned", "Cloned 8ch"};
static const QStringList STR_SUBTYPE_FRSKYR9 {"915 MHz", "868 MHz", "915 MHz 8-Channel", "868 MHz 8-Channel", "FCC", "---", "FCC 8-Channel"};
static const QStringList STR_SUBTYPE_PROPEL {"74-Z"};
static const QStringList STR_SUBTYPE_FRSKYL {"LR12", "LR12 6-Channel"};
static const QStringList STR_SUBTYPE_ESKY150V2 {"150 V2"};
static const QStringList STR_SUBTYPE_JJRC345 {"Standard", "SkyTumbler"};
static const QStringList STR_SUBTYPE_KYOSHO {"FHSS", "Hype"};
static const QStringList STR_SUBTYPE_RLINK {"Surface", "Air", "DumboRC"};
static const QStringList STR_SUBTYPE_ELRS {"Not Available WIP"};
static const QStringList STR_SUBTYPE_REALACC {"R11"};
static const QStringList STR_SUBTYPE_WFLY2 {"RF20x"};
static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT};
@@ -112,11 +119,11 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_MT99XX, 4, false, STR_SUBTYPE_MT99, nullptr},
{MODULE_SUBTYPE_MULTI_MJXQ, 6, false, STR_SUBTYPE_MJXQ, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FY326, 1, false, STR_SUBTYPE_FY326, nullptr},
{MODULE_SUBTYPE_MULTI_SFHSS, 0, true, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FUTABA, 0, true, STR_SUBTYPE_FUTABA, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_J6PRO, 0, false, NO_SUBTYPE, nullptr},
{MODULE_SUBTYPE_MULTI_HONTAI, 3, false, STR_SUBTYPE_HONTAI, nullptr},
{MODULE_SUBTYPE_MULTI_OLRS, 0, false, NO_SUBTYPE, STR_MULTI_RFPOWER},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 3, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_FS_AFHDS2A, 5, true, STR_SUBTYPE_AFHDS2A, STR_MULTI_SERVOFREQ},
{MODULE_SUBTYPE_MULTI_Q2X2, 2, false, STR_SUBTYPE_Q2X2, nullptr},
{MODULE_SUBTYPE_MULTI_WK_2X01, 5, false, STR_SUBTYPE_WK2x01, nullptr},
{MODULE_SUBTYPE_MULTI_Q303, 3, false, STR_SUBTYPE_Q303, nullptr},
@@ -136,20 +143,28 @@ const Multiprotocols multiProtocols {
{MODULE_SUBTYPE_MULTI_REDPINE, 1, false, STR_SUBTYPE_REDPINE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr},
{MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr},
{MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr},
{MODULE_SUBTYPE_MULTI_HEIGHT, 1, false, STR_SUBTYPE_HEIGHT, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_HOTT, 1, true, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FX816, 0, false, STR_SUBTYPE_FX816, nullptr},
{MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, STR_SUBTYPE_PELIKAN, nullptr},
{MODULE_SUBTYPE_MULTI_XK, 1, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, STR_SUBTYPE_XN297DUMP, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 4, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 3, true, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYX2, 5, true, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_FRSKY_R9, 6, true, STR_SUBTYPE_FRSKYR9, nullptr},
{MODULE_SUBTYPE_MULTI_PROPEL, 0, false, STR_SUBTYPE_PROPEL, nullptr},
{MODULE_SUBTYPE_MULTI_FRSKYL, 1, false, STR_SUBTYPE_FRSKYL, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_SKYARTEC, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ESKY150V2, 0, false, STR_SUBTYPE_ESKY150V2, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_JJRC345, 1, false, STR_SUBTYPE_JJRC345, nullptr},
{MODULE_SUBTYPE_MULTI_Q90C, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_KYOSHO, 1, false, STR_SUBTYPE_KYOSHO, nullptr},
{MODULE_SUBTYPE_MULTI_RLINK, 2, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_ELRS, 0, false, STR_SUBTYPE_ELRS, nullptr},
{MODULE_SUBTYPE_MULTI_REALACC, 0, false, STR_SUBTYPE_REALACC, nullptr},
{MODULE_SUBTYPE_MULTI_OMP, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MODULE_SUBTYPE_MULTI_WFLY2, 0, false, STR_SUBTYPE_WFLY2, STR_MULTI_OPTION},
{MODULE_SUBTYPE_MULTI_E016HV2, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE},
{MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION},
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
@@ -189,12 +204,13 @@ QString Multiprotocols::protocolToString(int protocol, bool custom)
{
static const QStringList strings({
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "Futaba", "J6 PRO","FQ777","Assan","Hontai","Open LRS",
"FlySky AFHDS2A", "Q2x2", "WK2x01", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie",
"Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761",
"KFPlan KF606", "Redpine", "Potensic", "ZSX", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
"KFPlan KF606", "Redpine", "Potensic", "ZSX", "Height", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816",
"Bayang RX", "Pelikan", "Tiger", "XK", "XN297 Dump", "FrSky X 2.1", "FrSky R9", "Propel", "FrSky L", "Skyartec",
"ESky 150v2", "DSM RX", "JJRC345", "Q90C"
"ESky 150v2", "DSM RX", "JJRC345", "Q90C", "Kyosho", "RadioLink", "ExpressLRS", "Realacc", "OMP", "M-Link", "Wfly 2",
"E016H v2"
});
return strings.value(protocol, CPN_STR_UNKNOWN_ITEM);
+32 -16
View File
@@ -45,7 +45,10 @@ inline int MAX_SWITCHES(Board::Type board, int version)
if (IS_TARANIS_X9D(board))
return 9;
if (IS_JUMPER_T12(board))
if (IS_FAMILY_T12(board))
return 8;
if (IS_TARANIS_X7(board))
return 8;
return Boards::getCapability(board, Board::Switches);
@@ -73,6 +76,8 @@ inline int MAX_POTS(Board::Type board, int version)
{
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 3;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots);
}
@@ -82,6 +87,8 @@ inline int MAX_POTS_STORAGE(Board::Type board, int version)
return 3;
if (version >= 219 && IS_FAMILY_HORUS_OR_T16(board))
return 5;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots);
}
@@ -89,6 +96,8 @@ inline int MAX_POTS_SOURCES(Board::Type board, int version)
{
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 5;
if (IS_FAMILY_T12(board))
return 2;
return Boards::getCapability(board, Board::Pots);
}
@@ -128,6 +137,14 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
return 16;
}
inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version)
{
if (IS_FAMILY_HORUS_OR_T16(board))
return 2;
else
return 0;
}
#define MAX_ROTARY_ENCODERS(board) 0
#define MAX_FLIGHT_MODES(board, version) 9
#define MAX_TIMERS(board, version) 3
@@ -300,7 +317,7 @@ class SourcesConversionTable: public ConversionTable {
}
}
for (int i=0; i<CPN_MAX_STICKS + MAX_POTS_SOURCES(board, version) + MAX_SLIDERS_SOURCES(board, version) + Boards::getCapability(board, Board::MouseAnalogs) + MAX_GYRO_ANALOGS(board, version); i++) {
for (int i=0; i<CPN_MAX_STICKS + MAX_POTS_SOURCES(board, version) + MAX_SLIDERS_SOURCES(board, version) + MAX_MOUSE_ANALOG_SOURCES(board, version) + MAX_GYRO_ANALOGS(board, version); i++) {
int offset = 0;
if (version <= 218 && IS_HORUS_X10(board) && i >= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version))
offset += 2;
@@ -1398,8 +1415,7 @@ class CustomFunctionsConversionTable: public ConversionTable {
addConversion(FuncAdjustGV1+i, val);
val++;
addConversion(FuncVolume, val++);
addConversion(FuncSetFailsafeInternalModule, val);
addConversion(FuncSetFailsafeExternalModule, val++);
addConversion(FuncSetFailsafe, val++);
addConversion(FuncRangeCheckInternalModule, val);
addConversion(FuncRangeCheckExternalModule, val++);
addConversion(FuncBindInternalModule, val);
@@ -1512,9 +1528,6 @@ class ArmCustomFunctionField: public TransformedField {
*((uint16_t *)_param) = fn.param;
*((uint8_t *)(_param+3)) = fn.func - FuncSetTimer1;
}
else if (fn.func >= FuncSetFailsafeInternalModule && fn.func <= FuncSetFailsafeExternalModule) {
*((uint16_t *)_param) = fn.func - FuncSetFailsafeInternalModule;
}
else if (fn.func >= FuncRangeCheckInternalModule && fn.func <= FuncRangeCheckExternalModule) {
*((uint16_t *)_param) = fn.func - FuncRangeCheckInternalModule;
}
@@ -1536,7 +1549,7 @@ class ArmCustomFunctionField: public TransformedField {
value = fn.param;
*((uint16_t *)_param) = value;
}
else if (fn.func == FuncPlayValue || fn.func == FuncVolume) {
else if (fn.func == FuncPlayValue || fn.func == FuncVolume || fn.func == FuncBacklight) {
unsigned int value;
sourcesConversionTable->exportValue(fn.param, (int &)value);
*((uint16_t *)_param) = value;
@@ -1579,7 +1592,7 @@ class ArmCustomFunctionField: public TransformedField {
else if (fn.func == FuncPlayPrompt || fn.func == FuncBackgroundMusic || fn.func == FuncPlayScript) {
memcpy(fn.paramarm, _param, sizeof(fn.paramarm));
}
else if (fn.func == FuncVolume) {
else if (fn.func == FuncVolume || fn.func == FuncBacklight) {
sourcesConversionTable->importValue(value, (int &)fn.param);
}
else if (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast) {
@@ -2145,15 +2158,16 @@ class ModuleUnionField: public UnionField<unsigned int> {
module(module)
{
internalField.Append(new UnsignedField<3>(this, module.access.receivers));
internalField.Append(new SpareBitsField<5>(this));
internalField.Append(new SpareBitsField<4>(this));
internalField.Append(new UnsignedField<1>(this, module.access.racingMode));
for (int i=0; i<PXX2_MAX_RECEIVERS_PER_MODULE; i++)
for (int i = 0; i < PXX2_MAX_RECEIVERS_PER_MODULE; i++)
internalField.Append(new CharField<8>(this, receiverName[i]));
memset(receiverName, 0, sizeof(receiverName));
}
bool select(const unsigned int& attr) const override
bool select(const unsigned int & attr) const override
{
return attr >= PULSES_ACCESS_ISRM && attr <= PULSES_ACCESS_R9M_LITE_PRO;
}
@@ -2298,7 +2312,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<2>(this, modelData.timers[i].countdownBeep));
internalField.Append(new BoolField<1>(this, modelData.timers[i].minuteBeep));
internalField.Append(new UnsignedField<2>(this, modelData.timers[i].persistent));
internalField.Append(new SpareBitsField<3>(this));
internalField.Append(new SignedField<2>(this, modelData.timers[i].countdownStart));
internalField.Append(new UnsignedField<1>(this, modelData.timers[i].direction));
if (HAS_LARGE_LCD(board))
internalField.Append(new ZCharField<8>(this, modelData.timers[i].name, "Timer name"));
else
@@ -2413,7 +2428,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
}
else {
internalField.Append(new SpareBitsField<6>(this));
internalField.Append(new SpareBitsField<3>(this));
internalField.Append(new UnsignedField<3>(this, modelData.thrTrimSwitch));
internalField.Append(new UnsignedField<2>(this, modelData.potsWarningMode));
}
@@ -2569,7 +2585,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
generalData(generalData),
board(board),
version(version),
inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + Boards::getCapability(board, Board::MouseAnalogs))
inputsCount(CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version) + MAX_SLIDERS_STORAGE(board, version) + MAX_MOUSE_ANALOG_SOURCES(board, version))
{
qCDebug(eepromImport) << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board).arg(version).arg(variant);
@@ -2711,7 +2727,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new BoolField<1>(this, generalData.disableRssiPoweroffAlarm));
internalField.Append(new UnsignedField<2>(this, generalData.usbMode));
internalField.Append(new UnsignedField<2>(this, generalData.jackMode));
internalField.Append(new SpareBitsField<1>(this));
internalField.Append(new BoolField<1>(this, generalData.sportPower));
}
else {
internalField.Append(new SpareBitsField<7>(this));
@@ -36,6 +36,9 @@
#define TARANIS_X9LITE_VARIANT 0x0800
#define TARANIS_X9LITES_VARIANT 0x0801
#define JUMPER_T12_VARIANT 0x4001
#define RADIOMASTER_TX12_VARIANT 0x4002
#define JUMPER_TLITE_VARIANT 0x4003
#define RADIOMASTER_T8_VARIANT 0x4004
class OpenTxGeneralData: public TransformedField {
public:
@@ -96,7 +99,7 @@ class ProtocolsConversionTable: public ConversionTable
addConversion(PULSES_ACCESS_R9M, val++);
addConversion(PULSES_PXX_R9M_LITE, val++);
addConversion(PULSES_ACCESS_R9M_LITE, val++);
addConversion(PULSES_PXX_R9M_LITE_PRO, val++);
addConversion(PULSES_GHOST, val++);
addConversion(PULSES_ACCESS_R9M_LITE_PRO, val++);
addConversion(PULSES_SBUS, val++);
@@ -104,6 +107,7 @@ class ProtocolsConversionTable: public ConversionTable
addConversion(PULSES_XJT_LITE_X16, val);
addConversion(PULSES_XJT_LITE_D8, val);
addConversion(PULSES_XJT_LITE_LR12, val++);
if (version >= 219) {
addConversion(PULSES_AFHDS3, val++);
}
@@ -60,12 +60,18 @@ const char * OpenTxEepromInterface::getName()
switch (board) {
case BOARD_JUMPER_T12:
return "OpenTX for Jumper T12";
case BOARD_JUMPER_TLITE:
return "OpenTX for Jumper T-Lite";
case BOARD_JUMPER_T16:
return "OpenTX for Jumper T16";
case BOARD_JUMPER_T18:
return "OpenTX for Jumper T18";
case BOARD_RADIOMASTER_TX16S:
return "OpenTX for Radiomaster TX16S";
case BOARD_RADIOMASTER_TX12:
return "OpenTX for Radiomaster TX12";
case BOARD_RADIOMASTER_T8:
return "OpenTX for Radiomaster T8";
case BOARD_TARANIS_X9D:
return "OpenTX for FrSky Taranis X9D";
case BOARD_TARANIS_X9DP:
@@ -334,7 +340,15 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
else if (IS_JUMPER_T12(board)) {
variant |= JUMPER_T12_VARIANT;
}
else if (IS_JUMPER_TLITE(board)) {
variant |= JUMPER_TLITE_VARIANT;
}
else if (IS_RADIOMASTER_TX12(board)) {
variant |= RADIOMASTER_TX12_VARIANT;
}
else if (IS_RADIOMASTER_T8(board)) {
variant |= RADIOMASTER_T8_VARIANT;
}
OpenTxGeneralData generator((GeneralSettings &)radioData.generalSettings, board, version, variant);
// generator.dump();
QByteArray data;
@@ -520,7 +534,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case MaxVolume:
return 23;
case MaxContrast:
if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
if (IS_TARANIS_SMALL(board))
return 30;
else
return 45;
@@ -540,7 +554,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case Simulation:
return 1;
case NumCurves:
return (HAS_LARGE_LCD(board) ? 32 : 16);
return 32;
case HasMixerNames:
return (IS_TARANIS_X9(board) ? 8 : 6);
case HasExpoNames:
@@ -615,7 +629,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdWidth:
if (IS_FAMILY_HORUS_OR_T16(board))
return 480;
else if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
else if (IS_TARANIS_SMALL(board))
return 128;
else if (IS_TARANIS(board))
return 212;
@@ -629,7 +643,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdDepth:
if (IS_FAMILY_HORUS_OR_T16(board))
return 16;
else if (IS_TARANIS_SMALL(board) || IS_JUMPER_T12(board))
else if (IS_TARANIS_SMALL(board))
return 1;
else if (IS_TARANIS(board))
return 4;
@@ -679,6 +693,12 @@ int OpenTxFirmware::getCapability(::Capability capability)
return TARANIS_XLITE_VARIANT;
else if (IS_JUMPER_T12(board))
return JUMPER_T12_VARIANT;
else if (IS_JUMPER_TLITE(board))
return JUMPER_TLITE_VARIANT;
else if (IS_RADIOMASTER_TX12(board))
return RADIOMASTER_TX12_VARIANT;
else if (IS_RADIOMASTER_T8(board))
return RADIOMASTER_T8_VARIANT;
else
return 0;
case MavlinkTelemetry:
@@ -696,6 +716,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
return IS_FAMILY_HORUS_OR_T16(board);
case HasSwitchableJack:
return IS_TARANIS_XLITES(board);
case HasSportConnector:
return IS_ACCESS_RADIO(board, id) || IS_TARANIS_X7(board) || IS_HORUS_X10(board) || IS_TARANIS_XLITE(board);
case PwrButtonPress:
return IS_HORUS_OR_TARANIS(board) && (board!=Board::BOARD_TARANIS_X9D) && (board!=Board::BOARD_TARANIS_X9DP);
case Sensors:
@@ -731,14 +753,14 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
return true;
case PULSES_PXX_XJT_X16:
case PULSES_PXX_XJT_LR12:
return !IS_ACCESS_RADIO(board, id) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board);
return !IS_ACCESS_RADIO(board, id) && !IS_FAMILY_T16(board) && !IS_FAMILY_T12(board);
case PULSES_PXX_XJT_D8:
return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board) && !IS_JUMPER_T12(board);
return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && !IS_FAMILY_T16(board) && !IS_FAMILY_T12(board);
case PULSES_ACCESS_ISRM:
case PULSES_ACCST_ISRM_D16:
return IS_ACCESS_RADIO(board, id);
case PULSES_MULTIMODULE:
return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board);
return id.contains("internalmulti") || IS_RADIOMASTER_TX16S(board) || IS_JUMPER_T18(board) || IS_RADIOMASTER_TX12(board) || IS_JUMPER_TLITE(board);
default:
return false;
}
@@ -760,16 +782,17 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
case PULSES_MULTIMODULE:
case PULSES_CROSSFIRE:
case PULSES_AFHDS3:
case PULSES_GHOST:
return true;
case PULSES_ACCESS_R9M:
return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess"));
return IS_ACCESS_RADIO(board, id) || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("externalaccessmod"));
case PULSES_PXX_R9M_LITE:
case PULSES_ACCESS_R9M_LITE:
case PULSES_ACCESS_R9M_LITE_PRO:
case PULSES_XJT_LITE_X16:
case PULSES_XJT_LITE_D8:
case PULSES_XJT_LITE_LR12:
return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board));
return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_TLITE(board));
default:
return false;
}
@@ -940,6 +963,21 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
variantError = true;
}
}
else if (IS_JUMPER_TLITE(board)) {
if (variant != JUMPER_TLITE_VARIANT) {
variantError = true;
}
}
else if (IS_RADIOMASTER_TX12(board)) {
if (variant != RADIOMASTER_TX12_VARIANT) {
variantError = true;
}
}
else if (IS_RADIOMASTER_T8(board)) {
if (variant != RADIOMASTER_T8_VARIANT) {
variantError = true;
}
}
else if (IS_TARANIS(board)) {
if (variant != 0) {
variantError = true;
@@ -1188,19 +1226,19 @@ void registerOpenTxFirmwares()
firmware->addOption("horussticks", Firmware::tr("Horus gimbals installed (Hall sensors)"));
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX + AFHDS3);
addOpenTxRfOptions(firmware, EU + FLEX);
/* FrSky X9-Lite board */
firmware = new OpenTxFirmware("opentx-x9lite", Firmware::tr("FrSky Taranis X9-Lite"), BOARD_TARANIS_X9LITE);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky X9-LiteS board */
firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky X7 board */
firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7);
@@ -1218,7 +1256,7 @@ void registerOpenTxFirmwares()
firmware = new OpenTxFirmware("opentx-xlites", Firmware::tr("FrSky Taranis X-Lite S/PRO"), BOARD_TARANIS_XLITES);
addOpenTxTaranisOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
addOpenTxRfOptions(firmware, FLEX);
/* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
@@ -1231,6 +1269,7 @@ void registerOpenTxFirmwares()
firmware = new OpenTxFirmware("opentx-x10", Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
firmware->addOption("externalaccessmod", Firmware::tr("Support hardware mod: R9M ACCESS"));
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
@@ -1244,6 +1283,7 @@ void registerOpenTxFirmwares()
firmware = new OpenTxFirmware("opentx-x12s", Firmware::tr("FrSky Horus X12S"), BOARD_HORUS_X12S);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalaccess", Firmware::tr("Support for ACCESS internal module replacement"));
firmware->addOption("externalaccessmod", Firmware::tr("Support hardware mod: R9M ACCESS"));
firmware->addOption("pcbdev", Firmware::tr("Use ONLY with first DEV pcb version"));
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
@@ -1257,29 +1297,63 @@ void registerOpenTxFirmwares()
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T-Lite board */
firmware = new OpenTxFirmware("opentx-tlite", QCoreApplication::translate("Firmware", "Jumper T-Lite"), BOARD_JUMPER_TLITE);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
addOpenTxFrskyOptions(firmware);
firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module"));
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
firmware->addOption("externalaccessmod", Firmware::tr("Support hardware mod: R9M ACCESS"));
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
/* Radiomaster TX12 board */
firmware = new OpenTxFirmware("opentx-tx12", QCoreApplication::translate("Firmware", "Radiomaster TX12"), BOARD_RADIOMASTER_TX12);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* Radiomaster T8 board */
firmware = new OpenTxFirmware("opentx-t8", QCoreApplication::translate("Firmware", "Radiomaster T8"), BOARD_RADIOMASTER_T8);
addOpenTxCommonOptions(firmware);
firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support"));
firmware->addOption("nogvars", Firmware::tr("Disable Global variables"));
firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen"));
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, NONE);
firmware->addOption("bindkey", Firmware::tr("Allow bind using bind key"));
/* Radiomaster TX16S board */
firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16s / TX16s Hall / TX16s Masterfire"), BOARD_RADIOMASTER_TX16S);
firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
static const Firmware::Option opt_bt("bluetooth", Firmware::tr("Support for bluetooth module"));
static const Firmware::Option opt_internal_gps("internalgps", Firmware::tr("Support internal GPS"));
firmware->addOptionsGroup({opt_bt, opt_internal_gps});
firmware->addOption("externalaccessmod", Firmware::tr("Support hardware mod: R9M ACCESS"));
registerOpenTxFirmware(firmware);
/* Jumper T18 board */
firmware = new OpenTxFirmware("opentx-t18", Firmware::tr("Jumper T18"), BOARD_JUMPER_T18);
addOpenTxFrskyOptions(firmware);
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
firmware->addOption("externalaccessmod", Firmware::tr("Support hardware mod: R9M ACCESS"));
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
+61
View File
@@ -0,0 +1,61 @@
/*
* 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.
*/
#include "output_data.h"
#include "radiodata.h"
#include "radiodataconversionstate.h"
void LimitData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(LimitData));
min = -1000;
max = +1000;
}
bool LimitData::isEmpty() const
{
LimitData tmp;
return !memcmp(this, &tmp, sizeof(LimitData));
}
QString LimitData::minToString() const
{
return QString::number((qreal)min / 10);
}
QString LimitData::maxToString() const
{
return QString::number((qreal)max / 10);
}
QString LimitData::revertToString() const
{
return revert ? tr("INV") : tr("NOR");
}
QString LimitData::nameToString(int index) const
{
return RadioData::getElementName(tr("CH"), index + 1, name);
}
QString LimitData::offsetToString() const
{
return QString::number((qreal)offset / 10, 'f', 1);
}
+52
View File
@@ -0,0 +1,52 @@
/*
* 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.
*/
#pragma once
#include "curvereference.h"
#include <QtCore>
#define LIMITDATA_NAME_LEN 6
class LimitData {
Q_DECLARE_TR_FUNCTIONS(LimitData)
public:
LimitData() { clear(); }
int min;
int max;
bool revert;
int offset;
int ppmCenter;
bool symetrical;
int failsafe;
char name[LIMITDATA_NAME_LEN + 1];
CurveReference curve;
void clear();
bool isEmpty() const;
QString minToString() const;
QString maxToString() const;
QString offsetToString() const;
QString revertToString() const;
QString nameToString(int index) const;
};
-17
View File
@@ -22,23 +22,6 @@
#include "radiodataconversionstate.h"
#include "eeprominterface.h"
// static
QString RadioData::getElementName(const QString & prefix, unsigned int index, const char * name, bool padding)
{
QString result = prefix;
if (padding)
result += QString("%1").arg(index, 2, 10, QChar('0'));
else
result += QString("%1").arg(index);
if (name) {
QString trimmed = QString(name).trimmed();
if (trimmed.length() > 0) {
result += ":" + QString(name).trimmed();
}
}
return result;
}
RadioData::RadioData()
{
models.resize(getCurrentFirmware()->getCapability(Models));
+6 -5
View File
@@ -1,9 +1,10 @@
#ifndef _RADIODATA_H_
#define _RADIODATA_H_
#pragma once
#include "generalsettings.h"
#include "modeldata.h"
#include "datahelpers.h" // required for getElementName
#include <QtCore>
class RadioDataConversionState;
@@ -32,10 +33,10 @@ class RadioData {
void fixModelFilenames();
QString getNextModelFilename();
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false);
// leave here until all calls repointed
static QString getElementName(const QString & prefix, unsigned int index, const char * name = 0, bool padding = false)
{ return DataHelpers::getElementName(prefix, index, name, padding); }
protected:
void fixModelFilename(unsigned int index);
};
#endif // _RADIODATA_H_
+64 -121
View File
@@ -60,7 +60,7 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
result.min = -30000 * result.step;
result.max = +30000 * result.step;
result.decimals = sensor.prec;
result.unit = sensor.unitString();
result.unit = SensorData::unitToString(qr.quot);
break;
}
@@ -140,32 +140,17 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
};
static const QString telemetry[] = {
tr("Batt"), tr("Time"), tr("Timer1"), tr("Timer2"), tr("Timer3"),
tr("RAS"), tr("RSSI Tx"), tr("RSSI Rx"),
tr("A1"), tr("A2"), tr("A3"), tr("A4"),
tr("Alt"), tr("Rpm"), tr("Fuel"), tr("T1"), tr("T2"),
tr("Speed"), tr("Dist"), tr("GPS Alt"),
tr("Cell"), tr("Cells"), tr("Vfas"), tr("Curr"), tr("Cnsp"), tr("Powr"),
tr("AccX"), tr("AccY"), tr("AccZ"),
tr("Hdg "), tr("VSpd"), tr("AirSpeed"), tr("dTE"),
tr("A1-"), tr("A2-"), tr("A3-"), tr("A4-"),
tr("Alt-"), tr("Alt+"), tr("Rpm+"), tr("T1+"), tr("T2+"), tr("Speed+"), tr("Dist+"), tr("AirSpeed+"),
tr("Cell-"), tr("Cells-"), tr("Vfas-"), tr("Curr+"), tr("Powr+"),
tr("ACC"), tr("GPS Time"),
};
static const QString rotary[] = { tr("REa"), tr("REb") };
if (index<0) {
return tr("???");
return QString(CPN_STR_UNKNOWN_ITEM);
}
QString result;
int genAryIdx = 0;
switch (type) {
case SOURCE_TYPE_NONE:
return tr("----");
return QString(CPN_STR_NONE_ITEM);
case SOURCE_TYPE_VIRTUAL_INPUT:
{
@@ -176,7 +161,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
}
case SOURCE_TYPE_LUA_OUTPUT:
return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16));
return tr("LUA%1%2").arg(index / 16 + 1).arg(QChar('a' + index % 16));
case SOURCE_TYPE_STICK:
if (generalSettings) {
@@ -208,10 +193,10 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return result;
case SOURCE_TYPE_CUSTOM_SWITCH:
return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString();
return RawSwitch(SWITCH_TYPE_VIRTUAL, index + 1).toString();
case SOURCE_TYPE_CYC:
return tr("CYC%1").arg(index+1);
return tr("CYC%1").arg(index + 1);
case SOURCE_TYPE_PPM:
return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1);
@@ -223,7 +208,16 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return LimitData().nameToString(index);
case SOURCE_TYPE_SPECIAL:
return CHECK_IN_ARRAY(special, index);
if (index >= SOURCE_TYPE_SPECIAL_TIMER1_IDX && index <= SOURCE_TYPE_SPECIAL_TIMER1_IDX + CPN_MAX_TIMERS - 1) {
if (model)
result = model->timers[index - SOURCE_TYPE_SPECIAL_TIMER1_IDX].nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX);
else
result = TimerData().nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX);
}
else
result = CHECK_IN_ARRAY(special, index);
return result;
case SOURCE_TYPE_TELEMETRY:
{
@@ -244,7 +238,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return GVarData().nameToString(index);
default:
return tr("???");
return QString(CPN_STR_UNKNOWN_ITEM);
}
}
@@ -347,111 +341,40 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType));
if (type == SOURCE_TYPE_STICK) {
if (cstate.toBoard.getCapability(Board::Sliders)) {
if (index >= cstate.fromBoard.getCapability(Board::Sticks) + cstate.fromBoard.getCapability(Board::Pots)) {
// 1st slider alignment
index += cstate.toBoard.getCapability(Board::Pots) - cstate.fromBoard.getCapability(Board::Pots);
}
if (isSlider(0, cstate.fromType)) {
// LS and RS sliders are after 2 aux sliders on X12 and X9E
if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
if (index >= 7) {
index += 2; // LS/RS to LS/RS
}
}
else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
if (index >= 7 && index <= 8) {
index += 2; // aux sliders to spare analogs (which may not exist, this is validated later)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (index >= 9 && index <= 10) {
index -= 2; // LS/RS to LS/RS
}
}
}
}
if (IS_TARANIS(cstate.toType) && IS_FAMILY_HORUS_OR_T16(cstate.fromType)) {
if (index == 6)
index = 5; // pot S2 to S2
else if (index == 5)
index = -1; // 6P on Horus doesn't exist on Taranis
}
else if (IS_FAMILY_HORUS_OR_T16(cstate.toType) && IS_TARANIS(cstate.fromType) && index == 5)
{
index = 6; // pot S2 to S2
}
} // SOURCE_TYPE_STICK
QStringList fromStickList(getStickList(cstate.fromBoard));
QStringList toStickList(getStickList(cstate.toBoard));
index = toStickList.indexOf(fromStickList.at(oldData.id));
// index set to -1 if no match found
// perform forced mapping
}
if (type == SOURCE_TYPE_SWITCH) {
// SWI to SWR don't exist on !X9E board
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
if (index >= 8) {
index = index % 8;
evt = RadioDataConversionState::EVT_CVRT;
QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
QStringList toSwitchList(getSwitchList(cstate.toBoard));
index = toSwitchList.indexOf(fromSwitchList.at(oldData.id));
// index set to -1 if no match found
// perform forced mapping
if (index < 0) {
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on X7 board
index = toSwitchList.indexOf("SD");
if (index >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (IS_FAMILY_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on T12 board
index = toSwitchList.indexOf("SD");
if (index >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
}
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on X7 board
if (index == 4 || index == 6) {
index = 3; // SG and SE to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (index == 5) {
index = 4; // SF to SF
}
else if (index == 7) {
index = 5; // SH to SH
}
}
else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on T12 board
if (index == 4 || index == 6) {
index = 3; // SG and SE to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (index == 5) {
index = 4; // SF to SF
}
else if (index == 7) {
index = 5; // SH to SH
}
}
// Compensate for SE and SG on X9/Horus board if converting from X7
else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
else if (index == 5) {
index = 7; // SH to SH
}
}
else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
else if (index == 5) {
index = 7; // SH to SH
}
}
else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (index == 4) {
index = 5; // SF to SF
}
else if (index == 5) {
index = 7; // SH to SH
}
}
} // SOURCE_TYPE_SWITCH
}
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
if (index < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
index = -1; // TODO: better way to flag invalid sources?
type = MAX_SOURCE_TYPE;
// no source is safer than an invalid one
clear();
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toModel(), cstate.toGS(), cstate.toType)));
@@ -463,3 +386,23 @@ RawSource RawSource::convert(RadioDataConversionState & cstate)
return *this;
}
QStringList RawSource::getStickList(Boards board) const
{
QStringList ret;
for (int i = 0; i < board.getCapability(Board::MaxAnalogs); i++) {
ret.append(board.getAnalogInputName(i));
}
return ret;
}
QStringList RawSource::getSwitchList(Boards board) const
{
QStringList ret;
for (int i = 0; i < board.getCapability(Board::Switches); i++) {
ret.append(board.getSwitchInfo(i).name);
}
return ret;
}
+5
View File
@@ -178,6 +178,9 @@ enum RawSourceType {
MAX_SOURCE_TYPE
};
constexpr int SOURCE_TYPE_STICK_THR_IDX { 3 }; // TODO is there a function to determine index?
constexpr int SOURCE_TYPE_SPECIAL_TIMER1_IDX { 2 }; // TODO temp const until Timers own source type
class RawSourceRange
{
Q_DECLARE_TR_FUNCTIONS(RawSourceRange)
@@ -252,6 +255,8 @@ class RawSource {
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool isSet() const { return type != SOURCE_TYPE_NONE || index != 0; }
void clear() { type = SOURCE_TYPE_NONE; index = 0; }
QStringList getStickList(Boards board) const;
QStringList getSwitchList(Boards board) const;
bool operator == ( const RawSource & other) const {
return (this->type == other.type) && (this->index == other.index);
+33 -61
View File
@@ -59,7 +59,7 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen
tr("THs"), tr("TH%"), tr("THt")
};
const QStringList directionIndicators = QStringList()
static const QStringList directionIndicators = QStringList()
<< CPN_STR_SW_INDICATOR_UP
<< CPN_STR_SW_INDICATOR_NEUT
<< CPN_STR_SW_INDICATOR_DN;
@@ -184,77 +184,39 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
RadioDataConversionState::EventType evt = RadioDataConversionState::EVT_NONE;
RadioDataConversionState::LogField oldData(index, toString(cstate.fromType, cstate.fromGS(), cstate.fromModel()));
int newIdx = 0;
if (type == SWITCH_TYPE_SWITCH) {
int srcIdx = div(abs(index)-1, 3).quot; // raw source index
int delta = 0;
// SWI to SWR don't exist on !X9E board
if (!IS_TARANIS_X9E(cstate.toType) && IS_TARANIS_X9E(cstate.fromType)) {
if (srcIdx > 7) {
index %= 24;
evt = RadioDataConversionState::EVT_CVRT;
}
}
// No SE and SG on X7 board
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
if (srcIdx == 4 || srcIdx == 5) {
delta = 3; // SE to SD & SF to SF
if (srcIdx == 4)
div_t swtch = div(abs(index) - 1, 3); // rawsource index
QStringList fromSwitchList(getSwitchList(cstate.fromBoard));
QStringList toSwitchList(getSwitchList(cstate.toBoard));
// set to -1 if no match found
newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot));
// perform forced mapping
if (newIdx < 0) {
if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on X7 board
newIdx = toSwitchList.indexOf("SD");
if (newIdx >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 6) {
delta = 9; // SG to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 7) {
delta = 6; // SH to SH
}
}
else if (IS_JUMPER_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
if (srcIdx == 4 || srcIdx == 5) {
delta = 3; // SE to SD & SF to SF
if (srcIdx == 4)
else if (IS_FAMILY_T12(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) {
// No SE and SG on T12 board
newIdx = toSwitchList.indexOf("SD");
if (newIdx >= 0)
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 6) {
delta = 9; // SG to SD
evt = RadioDataConversionState::EVT_CVRT;
}
else if (srcIdx == 7) {
delta = 6; // SH to SH
}
}
// Compensate for SE and SG on X9/Horus board if converting from X7
else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_TARANIS_X7(cstate.fromType)) {
if (srcIdx == 4) {
delta = -3; // SF to SF
}
else if (srcIdx == 5) {
delta = -6; // SH to SH
}
}
else if ((IS_TARANIS_X9(cstate.toType) || IS_FAMILY_HORUS_OR_T16(cstate.toType)) && IS_JUMPER_T12(cstate.fromType)) {
if (srcIdx == 4) {
delta = -3; // SF to SF
}
else if (srcIdx == 5) {
delta = -6; // SH to SH
}
}
if (index < 0) {
delta = -delta; // invert for !switch
}
index -= delta;
if (newIdx >= 0)
index = (newIdx * 3 + 1 + swtch.rem) * (index < 0 ? -1 : 1);
} // SWITCH_TYPE_SWITCH
// final validation (we do not pass model to isAvailable() because we don't know what has or hasn't been converted)
if (!isAvailable(NULL, cstate.toGS(), cstate.toType)) {
if (newIdx < 0 || !isAvailable(NULL, cstate.toGS(), cstate.toType)) {
cstate.setInvalid(oldData);
type = MAX_SWITCH_TYPE; // TODO: better way to flag invalid switches?
// no switch is safer than an invalid one
clear();
}
else if (evt == RadioDataConversionState::EVT_CVRT) {
cstate.setConverted(oldData, RadioDataConversionState::LogField(index, toString(cstate.toType, cstate.toGS(), cstate.toModel())));
@@ -266,3 +228,13 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate)
return *this;
}
QStringList RawSwitch::getSwitchList(Boards board) const
{
QStringList ret;
for (int i = 0; i < board.getCapability(Board::Switches); i++) {
ret.append(board.getSwitchInfo(i).name);
}
return ret;
}
+1
View File
@@ -89,6 +89,7 @@ class RawSwitch {
bool isAvailable(const ModelData * const model = NULL, const GeneralSettings * const gs = NULL, Board::Type board = Board::BOARD_UNKNOWN) const;
bool isSet() const { return type != SWITCH_TYPE_NONE || index != 0; }
void clear() { type = SWITCH_TYPE_NONE; index = 0; }
QStringList getSwitchList(Boards board) const;
bool operator== ( const RawSwitch& other) const {
return (this->type == other.type) && (this->index == other.index);
+421 -16
View File
@@ -19,9 +19,9 @@
*/
#include "sensordata.h"
#include "radiodata.h"
#include "modeldata.h"
#include "eeprominterface.h"
#include "compounditemmodels.h"
void SensorData::updateUnit()
{
@@ -31,9 +31,322 @@ void SensorData::updateUnit()
}
}
QString SensorData::unitString() const
QString SensorData::nameToString(int index) const
{
switch (unit) {
return DataHelpers::getElementName(tr("TELE"), index + 1, label);
}
QString SensorData::getOrigin(const ModelData * model) const
{
if (type != TELEM_TYPE_CUSTOM || !id)
return QString();
const ModuleData & module = model->moduleData[moduleIdx];
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) {
return QString(module.access.receiverName[rxIdx]);
}
else {
return QString();
}
}
bool SensorData::isEmpty() const
{
return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0);
}
QString SensorData::idToString() const
{
return idToString(id);
}
QString SensorData::typeToString() const
{
return typeToString(type);
}
QString SensorData::formulaToString() const
{
return formulaToString(formula);
}
QString SensorData::cellIndexToString() const
{
return cellIndexToString(index);
}
QString SensorData::unitToString() const
{
return unitToString(unit);
}
QString SensorData::precToString() const
{
return precToString(prec);
}
int SensorData::getMask() const
{
int mask = 0;
if (type == TELEM_TYPE_CALCULATED) {
if (formula < TELEM_FORMULA_CELL)
mask |= SENSOR_ISCONFIGURABLE | SENSOR_HAS_POSITIVE;
if (formula == TELEM_FORMULA_DIST)
mask |= SENSOR_HAS_GPS;
if (formula == TELEM_FORMULA_CELL)
mask |= SENSOR_HAS_CELLS;
if (formula == TELEM_FORMULA_CONSUMPTION)
mask |= SENSOR_HAS_CONSUMPTION;
if (formula <= TELEM_FORMULA_MULTIPLY)
mask |= SENSOR_HAS_SOURCES_12;
if (formula < TELEM_FORMULA_MULTIPLY)
mask |= SENSOR_HAS_SOURCES_34;
if (formula == TELEM_FORMULA_TOTALIZE)
mask |= SENSOR_HAS_TOTALIZE;
}
else {
if (unit < UNIT_FIRST_VIRTUAL)
mask |= (SENSOR_ISCONFIGURABLE | SENSOR_HAS_RATIO | SENSOR_HAS_POSITIVE);
}
if (mask & SENSOR_ISCONFIGURABLE && unit != UNIT_FAHRENHEIT)
mask |= SENSOR_HAS_PRECISION;
return mask;
}
constexpr char FMT_LABEL[] { "<b>%1:</b> " };
constexpr char FMT_VALUE[] { "%1 " };
constexpr char FMT_LABEL_VALUE[] { "<b>%1:</b> %2 " };
QString SensorData::paramsToString(const ModelData * model) const
{
if (!isAvailable())
return "";
QString str;
int mask = getMask();
if (type == TELEM_TYPE_CALCULATED) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Formula")).arg(formulaToString()));
}
else {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Id")).arg(idToString()));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Instance")).arg(instance));
}
if (mask & SENSOR_HAS_CELLS) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Sensor")).arg(sourceToString(model, source)));
str.append(QString(FMT_VALUE).arg(cellIndexToString()));
}
if (mask & SENSOR_HAS_SOURCES_12) {
str.append(QString(FMT_LABEL).arg(tr("Sources")));
for (int i = 0; i < 4; i++) {
if (i < 2 || mask & SENSOR_HAS_SOURCES_34) {
str.append(QString(FMT_VALUE).arg(sourceToString(model, sources[i])));
}
}
}
if (mask & SENSOR_HAS_CONSUMPTION || mask & SENSOR_HAS_TOTALIZE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Sensor")).arg(sourceToString(model, amps)));
if (mask & SENSOR_HAS_GPS) {
str.append(QString(FMT_LABEL_VALUE).arg(tr("GPS")).arg(sourceToString(model, gps)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Alt")).arg(sourceToString(model, alt)));
}
if (mask & SENSOR_ISCONFIGURABLE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Unit")).arg(unitToString()));
if (mask & SENSOR_HAS_PRECISION)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Precision")).arg(precToString()));
if (mask & SENSOR_HAS_RATIO) {
if (unit != UNIT_RPMS) {
int precsn = prec == 0 ? 1 : pow(10, prec);
str.append(QString(FMT_LABEL_VALUE).arg(tr("Ratio")).arg((float)ratio / 10));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Offset")).arg(QString::number((float)offset / precsn, 'f', prec)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Auto Offset")).arg(DataHelpers::boolToString(autoOffset, DataHelpers::BOOL_FMT_YN)));
}
else {
str.append(QString(FMT_LABEL_VALUE).arg(tr("Blades")).arg(ratio)); // TODO refactor to dedicated RPMS field
str.append(QString(FMT_LABEL_VALUE).arg(tr("Multiplier")).arg(offset)); // TODO refactor to dedicated RPMS field
}
}
if (mask & SENSOR_ISCONFIGURABLE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Filter")).arg(DataHelpers::boolToString(filter, DataHelpers::BOOL_FMT_YN)));
if (type == TELEM_TYPE_CALCULATED)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Persist")).arg(DataHelpers::boolToString(persistent, DataHelpers::BOOL_FMT_YN)));
if (mask & SENSOR_HAS_POSITIVE)
str.append(QString(FMT_LABEL_VALUE).arg(tr("Positive")).arg(DataHelpers::boolToString(onlyPositive, DataHelpers::BOOL_FMT_YN)));
str.append(QString(FMT_LABEL_VALUE).arg(tr("Log")).arg(DataHelpers::boolToString(logs, DataHelpers::BOOL_FMT_YN)));
return str;
}
FieldRange SensorData::getRatioRange() const
{
FieldRange result;
if (unit == SensorData::UNIT_RPMS) {
result.decimals = 0;
result.max = 30000;
result.min = 1;
result.step = 1;
}
else {
result.decimals = 1;
result.max = 30000;
result.min = 0;
result.step = 0.1;
}
return result;
}
FieldRange SensorData::getOffsetRange() const
{
FieldRange result;
if (unit == SensorData::UNIT_RPMS) {
result.decimals = 0;
result.max = 30000;
result.min = 1;
result.step = 1;
}
else {
result.decimals = prec;
result.max = 30000.0f / powf(10.0f, prec);
result.min = -result.max;
result.step = pow(0.1, prec);
}
return result;
}
void SensorData::formulaChanged()
{
switch (formula) {
case TELEM_FORMULA_CELL:
prec = 2;
unit = UNIT_VOLTS;
break;
case TELEM_FORMULA_CONSUMPTION:
prec = 0;
unit = UNIT_MAH;
break;
case TELEM_FORMULA_DIST:
prec = 0;
unit = UNIT_METERS;
break;
}
}
void SensorData::unitChanged()
{
if (unit == UNIT_FAHRENHEIT)
prec = 0;
}
// static
QString SensorData::idToString(const int value)
{
return QString::number(value, 16).toUpper();
}
// static
QString SensorData::typeToString(const int value)
{
switch(value) {
case TELEM_TYPE_CUSTOM:
return tr("Custom");
case TELEM_TYPE_CALCULATED:
return tr("Calculated");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString SensorData::formulaToString(const int value)
{
switch(value) {
case TELEM_FORMULA_ADD:
return tr("Add");
case TELEM_FORMULA_AVERAGE:
return tr("Average");
case TELEM_FORMULA_MIN:
return tr("Minimum");
case TELEM_FORMULA_MAX:
return tr("Maximum");
case TELEM_FORMULA_MULTIPLY:
return tr("Multiply");
case TELEM_FORMULA_TOTALIZE:
return tr("Totalize");
case TELEM_FORMULA_CELL:
return tr("Cell");
case TELEM_FORMULA_CONSUMPTION:
return tr("Consumption");
case TELEM_FORMULA_DIST:
return tr("Distance");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString SensorData::cellIndexToString(const int value)
{
if (value == TELEM_CELL_INDEX_LOWEST)
return tr("Lowest");
if (value > TELEM_CELL_INDEX_LOWEST && value < TELEM_CELL_INDEX_HIGHEST)
return tr("Cell %1").arg(value - TELEM_CELL_INDEX_LOWEST);
if (value== TELEM_CELL_INDEX_HIGHEST)
return tr("Highest");
if (value == TELEM_CELL_INDEX_DELTA)
return tr("Delta");
return CPN_STR_UNKNOWN_ITEM;
}
// static
QString SensorData::precToString(const int value)
{
return QString("0.%1").arg(QString(value, '0'));
}
// static
QString SensorData::sourceToString(const ModelData * model, const int index, const bool sign)
{
if (model) {
const QString prfx = sign ? index < 0 ? "-" : "+" : "";
if (abs(index) > 0) {
const SensorData &sd = model->sensorData[abs(index) - 1];
if (sd.type == SensorData::TELEM_TYPE_CUSTOM)
return QString("%1%2 (%3)").arg(prfx).arg(sd.label).arg(sd.getOrigin(model));
else
return QString("%1%2").arg(prfx).arg(sd.label);
}
else
return CPN_STR_NONE_ITEM;
}
return "";
}
// static
QString SensorData::unitToString(const int value)
{
switch (value) {
case UNIT_RAW:
return tr("Raw (-)");
case UNIT_VOLTS:
return tr("V");
case UNIT_AMPS:
@@ -84,26 +397,118 @@ QString SensorData::unitString() const
return tr("V");
case UNIT_MILLILITERS_PER_MINUTE:
return tr("ml/minute");
case UNIT_HERZ:
return tr("Hertz");
case UNIT_MS:
return tr("mS");
case UNIT_US:
return tr("uS");
default:
return "";
return CPN_STR_UNKNOWN_ITEM;
}
}
QString SensorData::nameToString(int index) const
// static
bool SensorData::isSourceAvailable(const ModelData * model, const int index)
{
return RadioData::getElementName(tr("TELE"), index + 1, label);
Firmware * firmware = getCurrentFirmware();
const int sensorcnt = firmware->getCapability(Sensors);
const int i = abs(index);
if (model && sensorcnt > 0 && i <= sensorcnt) {
if (i > 0)
return model->sensorData[i - 1].isAvailable();
else
return true;
}
return false;
}
QString SensorData::getOrigin(const ModelData * model) const
#define RSSI_ID 0xF101
// static
bool SensorData::isRssiSensorAvailable(const ModelData * model, const int value)
{
if (type != TELEM_TYPE_CUSTOM || !id)
return QString();
const ModuleData & module = model->moduleData[moduleIdx];
if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) {
return QString(module.access.receiverName[rxIdx]);
}
if (value == 0)
return true;
else {
return QString();
const SensorData &sensor = model->sensorData[abs(value) - 1];
return (sensor.isAvailable() && sensor.id == RSSI_ID);
}
}
// static
QString SensorData::rssiSensorToString(const ModelData * model, const int value)
{
if (value == 0)
return tr("(default)");
else
return sourceToString(model, value);
}
// static
AbstractStaticItemModel * SensorData::typeItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.type");
for (int i = 0; i <= TELEM_TYPE_LAST; i++) {
mdl->appendToItemList(typeToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::formulaItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.formula");
for (int i = 0; i <= TELEM_FORMULA_LAST; i++) {
mdl->appendToItemList(formulaToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::cellIndexItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.cellindex");
for (int i = 0; i <= TELEM_CELL_INDEX_LAST; i++) {
mdl->appendToItemList(cellIndexToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * SensorData::unitItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName("sensordata.unit");
for (int i = 0; i <= UNIT_MAX; i++) {
QString str = unitToString(i);
if (str != CPN_STR_UNKNOWN_ITEM)
mdl->appendToItemList(str, i);
}
mdl->loadItemList();
return mdl;
}
// static
PrecisionItemModel * SensorData::precisionItemModel()
{
PrecisionItemModel * mdl = new PrecisionItemModel(0, 2);
mdl->setName("sensordata.precision");
return mdl;
}
+57 -12
View File
@@ -18,16 +18,32 @@
* GNU General Public License for more details.
*/
#ifndef SENSORDATA_H
#define SENSORDATA_H
#pragma once
#include "datahelpers.h"
#include <QtCore>
constexpr int CPN_MAX_SENSORS = 60;
constexpr int CPN_MAX_SENSORS { 60 };
constexpr int SENSOR_LABEL_LEN { 4 };
constexpr int SENSOR_ISCONFIGURABLE { 1 << 1 };
constexpr int SENSOR_HAS_GPS { 1 << 2 };
constexpr int SENSOR_HAS_CELLS { 1 << 3 };
constexpr int SENSOR_HAS_CONSUMPTION { 1 << 4 };
constexpr int SENSOR_HAS_RATIO { 1 << 5 };
constexpr int SENSOR_HAS_TOTALIZE { 1 << 6 };
constexpr int SENSOR_HAS_SOURCES_12 { 1 << 7 };
constexpr int SENSOR_HAS_SOURCES_34 { 1 << 8 };
constexpr int SENSOR_HAS_POSITIVE { 1 << 9 };
constexpr int SENSOR_HAS_PRECISION { 1 << 10 };
class ModelData;
class AbstractStaticItemModel;
class PrecisionItemModel;
class SensorData {
Q_DECLARE_TR_FUNCTIONS(SensorData)
public:
@@ -35,7 +51,8 @@ class SensorData {
enum
{
TELEM_TYPE_CUSTOM,
TELEM_TYPE_CALCULATED
TELEM_TYPE_CALCULATED,
TELEM_TYPE_LAST = TELEM_TYPE_CALCULATED
};
enum
@@ -62,6 +79,7 @@ class SensorData {
TELEM_CELL_INDEX_6,
TELEM_CELL_INDEX_HIGHEST,
TELEM_CELL_INDEX_DELTA,
TELEM_CELL_INDEX_LAST = TELEM_CELL_INDEX_DELTA
};
enum
@@ -94,10 +112,10 @@ class SensorData {
UNIT_MILLILITERS,
UNIT_FLOZ,
UNIT_MILLILITERS_PER_MINUTE,
UNIT_MAX = UNIT_MILLILITERS_PER_MINUTE,
UNIT_SPARE1,
UNIT_SPARE2,
UNIT_SPARE3,
UNIT_HERZ,
UNIT_MS,
UNIT_US,
UNIT_MAX = UNIT_US,
UNIT_SPARE4,
UNIT_SPARE5,
UNIT_SPARE6,
@@ -133,7 +151,7 @@ class SensorData {
unsigned int moduleIdx;
unsigned int persistentValue;
unsigned int formula;
char label[4+1];
char label[SENSOR_LABEL_LEN + 1];
unsigned int unit;
unsigned int prec;
bool autoOffset;
@@ -162,10 +180,37 @@ class SensorData {
bool isAvailable() const { return strlen(label) > 0; }
void updateUnit();
QString unitString() const;
QString nameToString(int index) const;
QString getOrigin(const ModelData* model) const;
void clear() { memset(this, 0, sizeof(SensorData)); }
};
bool isEmpty() const;
QString idToString() const;
QString typeToString() const;
QString formulaToString() const;
QString cellIndexToString() const;
QString unitToString() const;
QString precToString() const;
int getMask() const;
QString paramsToString(const ModelData * model) const;
FieldRange getRatioRange() const;
FieldRange getOffsetRange() const;
void formulaChanged();
void unitChanged();
#endif // SENSORDATA_H
static QString sourceToString(const ModelData * model, const int index, const bool sign = false);
static bool isSourceAvailable(const ModelData * model, const int index);
static QString idToString(const int value);
static QString typeToString(const int value);
static QString formulaToString(const int value);
static QString cellIndexToString(const int value);
static QString unitToString(const int value);
static QString precToString(const int value);
static bool isRssiSensorAvailable(const ModelData * model, const int value);
static QString rssiSensorToString(const ModelData * model, const int value);
static AbstractStaticItemModel * typeItemModel();
static AbstractStaticItemModel * formulaItemModel();
static AbstractStaticItemModel * cellIndexItemModel();
static AbstractStaticItemModel * unitItemModel();
static PrecisionItemModel * precisionItemModel();
};
+188
View File
@@ -0,0 +1,188 @@
/*
* 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.
*/
#include "timerdata.h"
#include "radiodataconversionstate.h"
#include "compounditemmodels.h"
void TimerData::convert(RadioDataConversionState & cstate)
{
cstate.setComponent(tr("TMR"), 1);
cstate.setSubComp(tr("Timer %1").arg(cstate.subCompIdx + 1));
mode.convert(cstate);
}
void TimerData::clear()
{
memset(reinterpret_cast<void *>(this), 0, sizeof(TimerData));
mode = RawSwitch(SWITCH_TYPE_TIMER_MODE, 0);
}
bool TimerData::isEmpty()
{
return (mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0) && name[0] == '\0' && minuteBeep == 0 && countdownBeep == COUNTDOWNBEEP_SILENT && val == 0 && persistent == 0 /*&& pvalue == 0*/);
}
bool TimerData::isModeOff()
{
return mode == RawSwitch(SWITCH_TYPE_TIMER_MODE, 0);
}
QString TimerData::nameToString(int index) const
{
return DataHelpers::getElementName(tr("TMR", "as in Timer"), index + 1, name);
}
QString TimerData::countdownBeepToString() const
{
return countdownBeepToString(countdownBeep);
}
QString TimerData::countdownStartToString() const
{
if (countdownBeep == COUNTDOWNBEEP_SILENT)
return "";
else
return countdownStartToString(countdownStart);
}
QString TimerData::persistentToString(const bool verbose) const
{
return persistentToString(persistent, verbose);
}
QString TimerData::pvalueToString() const
{
return pvalueToString(pvalue);
}
QString TimerData::valToString() const
{
return valToString(val);
}
void TimerData::countdownBeepChanged()
{
if (countdownBeep == COUNTDOWNBEEP_SILENT)
countdownStart = 0;
}
// static
QString TimerData::countdownBeepToString(const int value)
{
switch(value) {
case COUNTDOWNBEEP_SILENT:
return tr("Silent");
case COUNTDOWNBEEP_BEEPS:
return tr("Beeps");
case COUNTDOWNBEEP_VOICE:
return tr("Voice");
case COUNTDOWNBEEP_HAPTIC:
return tr("Haptic");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::countdownStartToString(const int value)
{
switch(value) {
case COUNTDOWNSTART_5:
return tr("5s");
case COUNTDOWNSTART_10:
return tr("10s");
case COUNTDOWNSTART_20:
return tr("20s");
case COUNTDOWNSTART_30:
return tr("30s");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::persistentToString(const int value, const bool verbose)
{
switch(value) {
case PERSISTENT_NOT:
return verbose ? tr("Not persistent") : tr("NOT");
case PERSISTENT_FLIGHT:
return verbose ? tr("Persistent (flight)") : tr("Flight");
case PERSISTENT_MANUALRESET:
return verbose ? tr("Persistent (manual reset)") : tr("Manual reset");
default:
return CPN_STR_UNKNOWN_ITEM;
}
}
// static
QString TimerData::pvalueToString(const int value)
{
return DataHelpers::timeToString(value, TIMESTR_MASK_HRSMINS | TIMESTR_MASK_ZEROHRS);
}
// static
QString TimerData::valToString(const int value)
{
return DataHelpers::timeToString(value, TIMESTR_MASK_HRSMINS | TIMESTR_MASK_ZEROHRS);
}
// static
AbstractStaticItemModel * TimerData::countdownBeepItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_COUNTDOWNBEEP);
for (int i = 0; i < COUNTDOWNBEEP_COUNT; i++) {
mdl->appendToItemList(countdownBeepToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * TimerData::countdownStartItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_COUNTDOWNSTART);
for (int i = COUNTDOWNSTART_LAST; i >= COUNTDOWNSTART_FIRST; i--) {
mdl->appendToItemList(countdownStartToString(i), i);
}
mdl->loadItemList();
return mdl;
}
// static
AbstractStaticItemModel * TimerData::persistentItemModel()
{
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
mdl->setName(AIM_TIMER_PERSISTENT);
for (int i = 0; i < PERSISTENT_COUNT; i++) {
mdl->appendToItemList(persistentToString(i), i);
}
mdl->loadItemList();
return mdl;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* 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.
*/
#pragma once
#include "rawswitch.h"
#include "datahelpers.h"
#include <QtCore>
class RadioDataConversionState;
class AbstractStaticItemModel;
constexpr char AIM_TIMER_COUNTDOWNBEEP[] {"timerdata.countdownBeep"};
constexpr char AIM_TIMER_COUNTDOWNSTART[] {"timerdata.countdownStart"};
constexpr char AIM_TIMER_PERSISTENT[] {"timerdata.persistent"};
constexpr int TIMER_NAME_LEN {8};
class TimerData {
Q_DECLARE_TR_FUNCTIONS(TimerData)
public:
enum CountDownBeepType {
COUNTDOWNBEEP_SILENT,
COUNTDOWNBEEP_BEEPS,
COUNTDOWNBEEP_VOICE,
COUNTDOWNBEEP_HAPTIC,
COUNTDOWNBEEP_COUNT
};
enum CountDownStart {
COUNTDOWNSTART_30 = -2,
COUNTDOWNSTART_FIRST = COUNTDOWNSTART_30,
COUNTDOWNSTART_20,
COUNTDOWNSTART_10,
COUNTDOWNSTART_5,
COUNTDOWNSTART_LAST = COUNTDOWNSTART_5
};
enum PersistentType {
PERSISTENT_NOT,
PERSISTENT_FLIGHT,
PERSISTENT_MANUALRESET,
PERSISTENT_COUNT
};
TimerData() { clear(); }
RawSwitch mode;
char name[TIMER_NAME_LEN + 1];
bool minuteBeep;
unsigned int countdownBeep;
unsigned int val;
unsigned int persistent;
int countdownStart;
unsigned int direction;
int pvalue;
void convert(RadioDataConversionState & cstate);
void clear();
bool isEmpty();
bool isModeOff();
QString nameToString(int index) const;
QString countdownBeepToString() const;
QString countdownStartToString() const;
QString persistentToString(const bool verbose = true) const;
QString pvalueToString() const;
QString valToString() const;
void countdownBeepChanged();
static QString countdownBeepToString(const int value);
static QString countdownStartToString(const int value);
static QString persistentToString(const int value, const bool verbose = true);
static QString pvalueToString(const int value);
static QString valToString(const int value);
static AbstractStaticItemModel * countdownBeepItemModel();
static AbstractStaticItemModel * countdownStartItemModel();
static AbstractStaticItemModel * persistentItemModel();
};
+35 -31
View File
@@ -275,11 +275,12 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
// check hardware compatibility if requested
bool checkPassed = true;
if (g.checkHardwareCompatibility()) {
QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin");
if (!readFirmware(tempFirmware, progressDialog.progress())) {
QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
return;
checkPassed = false;
}
FirmwareInterface previousFirmware(tempFirmware);
qunlink(tempFirmware);
@@ -291,41 +292,44 @@ void FlashFirmwareDialog::startFlash(const QString &filename)
qDebug() << "startFlash: removing temporary file" << filename;
qunlink(filename);
}
return;
checkPassed = false;
}
}
// backup if requested
bool result = true;
QString backupFilename;
QString backupPath;
if (backup) {
backupPath = g.profile[g.id()].pBackupDir();
if (backupPath.isEmpty()) {
backupPath=g.backupDir();
if (checkPassed) {
// backup if requested
bool result = true;
QString backupFilename;
QString backupPath;
if (backup) {
backupPath = g.profile[g.id()].pBackupDir();
if (backupPath.isEmpty()) {
backupPath=g.backupDir();
}
backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
result = readEeprom(backupFilename, progressDialog.progress());
sleep(2);
}
backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
result = readEeprom(backupFilename, progressDialog.progress());
sleep(2);
// flash
result = (result && writeFirmware(filename, progressDialog.progress()));
// restore if backup requested
if (backup && result) {
sleep(2);
QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
if (!convertEEprom(backupFilename, restoreFilename, filename)) {
QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
restoreFilename = backupFilename;
}
if (!writeEeprom(restoreFilename, progressDialog.progress())) {
QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
}
}
progressDialog.progress()->setInfo(tr("Flashing done"));
}
// flash
result = (result && writeFirmware(filename, progressDialog.progress()));
// restore if backup requested
if (backup && result) {
sleep(2);
QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
if (!convertEEprom(backupFilename, restoreFilename, filename)) {
QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
restoreFilename = backupFilename;
}
if (!writeEeprom(restoreFilename, progressDialog.progress())) {
QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
}
}
progressDialog.progress()->setInfo(tr("Flashing done"));
progressDialog.exec();
if (isTempFileName(filename)) {
+1 -1
View File
@@ -28,4 +28,4 @@ qt5_wrap_ui(generaledit_SRCS ${generaledit_UIS})
qt5_wrap_cpp(generaledit_SRCS ${generaledit_HDRS})
add_library(generaledit ${generaledit_SRCS})
target_link_libraries(generaledit PRIVATE ${CPN_COMMON_LIB} Qt5::Multimedia)
target_link_libraries(generaledit PRIVATE datamodels ${CPN_COMMON_LIB} Qt5::Multimedia)
+9 -1
View File
@@ -28,6 +28,7 @@
#include "hardware.h"
#include "../modeledit/customfunctions.h"
#include "verticalscrollarea.h"
#include "compounditemmodels.h"
GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) :
QDialog(parent),
@@ -55,8 +56,14 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
}
}
sharedItemModels = new CompoundItemModelFactory(&generalSettings, nullptr);
sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource);
sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction);
sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam);
addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup"));
addTab(new CustomFunctionsPanel(this, NULL, generalSettings, firmware), tr("Global Functions"));
addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, sharedItemModels), tr("Global Functions"));
addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer"));
addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware"));
addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration"));
@@ -67,6 +74,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir
GeneralEdit::~GeneralEdit()
{
delete ui;
delete sharedItemModels;
}
void GeneralEdit::closeEvent(QCloseEvent *event)
+4 -2
View File
@@ -25,6 +25,8 @@
#include "eeprominterface.h"
#include "genericpanel.h"
class CompoundItemModelFactory;
namespace Ui {
class GeneralEdit;
}
@@ -56,7 +58,7 @@ class GeneralEdit : public QDialog
void getGeneralSwitchDefPos(int i, bool val);
void setSwitchDefPos();
void updateVarioPitchRange();
signals:
void modified();
@@ -71,7 +73,7 @@ class GeneralEdit : public QDialog
QVector<GenericPanel *> panels;
void addTab(GenericPanel *panel, QString text);
void closeEvent(QCloseEvent *event);
CompoundItemModelFactory *sharedItemModels;
};
#endif // _GENERALEDIT_H_
+5 -5
View File
@@ -158,7 +158,7 @@ ui(new Ui::GeneralSetup)
ui->usbModeLabel->hide();
ui->usbModeCB->hide();
}
if (firmware->getCapability(HasSwitchableJack)) {
ui->jackModeCB->setCurrentIndex(generalSettings.jackMode);
}
@@ -266,7 +266,7 @@ ui(new Ui::GeneralSetup)
ui->pwrOnDelayLabel->hide();
ui->pwrOnDelay->hide();
}
setValues();
lock = false;
@@ -505,13 +505,13 @@ void GeneralSetupPanel::on_splashScreenDuration_currentIndexChanged(int index)
emit modified();
}
void GeneralSetupPanel::on_pwrOnDelay_valueChanged()
void GeneralSetupPanel::on_pwrOnDelay_valueChanged(int)
{
generalSettings.pwrOnSpeed = 2 - ui->pwrOnDelay->value();
emit modified();
}
void GeneralSetupPanel::on_pwrOffDelay_valueChanged()
void GeneralSetupPanel::on_pwrOffDelay_valueChanged(int)
{
generalSettings.pwrOffSpeed = 2 - ui->pwrOffDelay->value();
emit modified();
@@ -650,7 +650,7 @@ void GeneralSetupPanel::on_backlightautoSB_editingFinished()
}
}
void GeneralSetupPanel::on_switchesDelay_valueChanged()
void GeneralSetupPanel::on_switchesDelay_valueChanged(int)
{
generalSettings.switchesDelay = (ui->switchesDelay->value() / 10) - 15;
emit modified();
+3 -3
View File
@@ -65,7 +65,7 @@ class GeneralSetupPanel : public GeneralPanel
void on_mavbaud_CB_currentIndexChanged(int index);
void on_voiceLang_CB_currentIndexChanged(int index);
void stickReverseEdited();
void on_switchesDelay_valueChanged();
void on_switchesDelay_valueChanged(int);
void on_blAlarm_ChkB_stateChanged();
void unlockSwitchEdited();
void on_beepVolume_SL_valueChanged();
@@ -89,8 +89,8 @@ class GeneralSetupPanel : public GeneralPanel
void on_contrastSB_editingFinished();
void on_registrationId_editingFinished();
void on_pwrOnDelay_valueChanged();
void on_pwrOffDelay_valueChanged();
void on_pwrOnDelay_valueChanged(int);
void on_pwrOffDelay_valueChanged(int);
private:
Ui::GeneralSetup *ui;
+4 -4
View File
@@ -1527,7 +1527,7 @@ Mode 4:
<string>Battery warning voltage.
This is the threashhold where the battery warning sounds.
Acceptable values are 5v..10v</string>
Acceptable values are 3v..12v</string>
</property>
<property name="prefix">
<string notr="true"/>
@@ -1539,7 +1539,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>12.000000000000000</double>
@@ -1679,7 +1679,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>16.000000000000000</double>
@@ -1708,7 +1708,7 @@ Acceptable values are 5v..10v</string>
<number>1</number>
</property>
<property name="minimum">
<double>4.000000000000000</double>
<double>3.000000000000000</double>
</property>
<property name="maximum">
<double>16.000000000000000</double>
+42 -12
View File
@@ -47,7 +47,15 @@ void HardwarePanel::setupSwitchType(int index, QLabel * label, AutoLineEdit * na
label->setText("SJ");
}
}
if (IS_JUMPER_T12(board)) {
else if (IS_RADIOMASTER_TX12(board)) {
if (index == 6) {
label->setText("SI");
}
else if (index == 7) {
label->setText("SJ");
}
}
else if (IS_FAMILY_T12(board)) {
if (index == 4) {
label->setText("SG");
}
@@ -101,6 +109,15 @@ void HardwarePanel::setupSliderType(int index, QLabel *label, AutoLineEdit *name
}
}
bool HardwarePanel::isSwitch3Pos(int idx)
{
Board::Type board = firmware->getBoard();
Board::SwitchInfo switchInfo = Boards::getSwitchInfo(board, idx);
switchInfo.config = Board::SwitchType(generalSettings.switchConfig[idx]);
return switchInfo.config == Board::SWITCH_3POS;
};
HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware):
GeneralPanel(parent, generalSettings, firmware),
ui(new Ui::Hardware)
@@ -127,6 +144,14 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->potsTypeSeparator_1->hide();
ui->potsTypeSeparator_2->hide();
}
if (firmware->getCapability(HasSportConnector)) {
ui->sportPower->setChecked(generalSettings.sportPower);
}
else {
ui->sportPower->hide();
ui->sportPowerLabel->hide();
}
setupPotType(0, ui->pot1Label, ui->pot1Name, ui->pot1Type);
setupPotType(1, ui->pot2Label, ui->pot2Name, ui->pot2Type);
@@ -139,17 +164,17 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
setupSliderType(2, ui->ls2Label, ui->ls2Name, ui->ls2Type);
setupSliderType(3, ui->rs2Label, ui->rs2Name, ui->rs2Type);
setupSwitchType(0, ui->saLabel, ui->saName, ui->saType);
setupSwitchType(1, ui->sbLabel, ui->sbName, ui->sbType);
setupSwitchType(2, ui->scLabel, ui->scName, ui->scType);
setupSwitchType(3, ui->sdLabel, ui->sdName, ui->sdType);
setupSwitchType(4, ui->seLabel, ui->seName, ui->seType);
setupSwitchType(5, ui->sfLabel, ui->sfName, ui->sfType, false); //switch does not support 3POS
setupSwitchType(6, ui->sgLabel, ui->sgName, ui->sgType);
setupSwitchType(7, ui->shLabel, ui->shName, ui->shType, false); //switch does not support 3POS
setupSwitchType(8, ui->siLabel, ui->siName, ui->siType);
setupSwitchType(9, ui->sjLabel, ui->sjName, ui->sjType);
setupSwitchType(10, ui->skLabel, ui->skName, ui->skType);
setupSwitchType(0, ui->saLabel, ui->saName, ui->saType, isSwitch3Pos(0));
setupSwitchType(1, ui->sbLabel, ui->sbName, ui->sbType, isSwitch3Pos(1));
setupSwitchType(2, ui->scLabel, ui->scName, ui->scType, isSwitch3Pos(2));
setupSwitchType(3, ui->sdLabel, ui->sdName, ui->sdType, isSwitch3Pos(3));
setupSwitchType(4, ui->seLabel, ui->seName, ui->seType, isSwitch3Pos(4));
setupSwitchType(5, ui->sfLabel, ui->sfName, ui->sfType, isSwitch3Pos(5));
setupSwitchType(6, ui->sgLabel, ui->sgName, ui->sgType, isSwitch3Pos(6));
setupSwitchType(7, ui->shLabel, ui->shName, ui->shType, isSwitch3Pos(7));
setupSwitchType(8, ui->siLabel, ui->siName, ui->siType, isSwitch3Pos(8));
setupSwitchType(9, ui->sjLabel, ui->sjName, ui->sjType, isSwitch3Pos(9));
setupSwitchType(10, ui->skLabel, ui->skName, ui->skType); // Here starts X9E, only 3 switches
setupSwitchType(11, ui->slLabel, ui->slName, ui->slType);
setupSwitchType(12, ui->smLabel, ui->smName, ui->smType);
setupSwitchType(13, ui->snLabel, ui->snName, ui->snType);
@@ -232,6 +257,11 @@ void HardwarePanel::on_filterEnable_stateChanged()
generalSettings.jitterFilter = !ui->filterEnable->isChecked();
}
void HardwarePanel::on_sportPower_stateChanged()
{
generalSettings.sportPower = ui->sportPower->isChecked();
}
void HardwarePanel::on_rtcCheckDisable_stateChanged()
{
generalSettings.rtcCheckDisable = !ui->rtcCheckDisable->isChecked();
+2
View File
@@ -50,6 +50,7 @@ class HardwarePanel : public GeneralPanel
void on_txVoltageCalibration_editingFinished();
void on_filterEnable_stateChanged();
void on_rtcCheckDisable_stateChanged();
void on_sportPower_stateChanged();
void on_serialPortMode_currentIndexChanged(int index);
@@ -62,6 +63,7 @@ class HardwarePanel : public GeneralPanel
Ui::Hardware *ui;
void setValues();
bool isSwitch3Pos(int idx);
};
#endif // _HARDWARE_H_
File diff suppressed because it is too large Load Diff
+21 -216
View File
@@ -32,6 +32,7 @@
#include "simulatorinterface.h"
#include "simulatormainwindow.h"
#include "storage/sdcard.h"
#include "filtereditemmodels.h"
#include <QFileDialog>
#include <QLabel>
@@ -117,7 +118,8 @@ void CompanionIcon::addImage(const QString & baseimage, Mode mode, State state)
* GVarGroup
*/
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step, bool allowGvars):
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step, FilteredItemModel * gvarModel):
QObject(),
weightGV(weightGV),
weightSB(weightSB),
@@ -131,8 +133,8 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
step(step),
lock(true)
{
if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) {
Helpers::populateGVCB(*weightCB, weight, model);
if (gvarModel && gvarModel->rowCount() > 0) {
weightCB->setModel(gvarModel);
connect(weightGV, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(weightCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
}
@@ -152,12 +154,19 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
void GVarGroup::gvarCBChanged(int state)
{
weightCB->setVisible(state);
if (weightSB)
if (!lock) {
weightCB->setVisible(state);
if (weightGV->isChecked()) {
// set CB to +GV1
int cnt = getCurrentFirmware()->getCapability(Gvars);
if (weightCB->count() > cnt)
weightCB->setCurrentIndex(cnt);
else
weightCB->setCurrentIndex(0);
}
weightSB->setVisible(!state);
else
weightSB->setVisible(!state);
valuesChanged();
valuesChanged();
}
}
void GVarGroup::valuesChanged()
@@ -168,7 +177,7 @@ void GVarGroup::valuesChanged()
else if (sb)
weight = sb->value();
else
weight = round(dsb->value()/step);
weight = round(dsb->value() / step);
emit valueChanged();
}
@@ -180,7 +189,7 @@ void GVarGroup::setWeight(int val)
int tval;
if (val>maxi || val<mini) {
if (val > maxi || val < mini) {
tval = deflt;
weightGV->setChecked(true);
weightSB->hide();
@@ -210,215 +219,10 @@ void GVarGroup::setWeight(int val)
lock = false;
}
/*
* CurveGroup
*/
CurveGroup::CurveGroup(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QComboBox * curveValueCB, QSpinBox * curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags):
QObject(),
curveTypeCB(curveTypeCB),
curveGVarCB(curveGVarCB),
curveValueCB(curveValueCB),
curveValueSB(curveValueSB),
curve(curve),
model(model),
flags(flags),
lock(false),
lastType(-1)
{
if (!(flags & HIDE_DIFF)) curveTypeCB->addItem(tr("Diff"), 0);
if (!(flags & HIDE_EXPO)) curveTypeCB->addItem(tr("Expo"), 1);
curveTypeCB->addItem(tr("Func"), 2);
curveTypeCB->addItem(tr("Curve"), 3);
curveValueCB->setMaxVisibleItems(10);
connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
update();
}
void CurveGroup::update()
{
lock = true;
int found = curveTypeCB->findData(curve.type);
if (found < 0) found = 0;
curveTypeCB->setCurrentIndex(found);
if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) {
curveGVarCB->setVisible(getCurrentFirmware()->getCapability(Gvars));
if (curve.value > 100 || curve.value < -100) {
curveGVarCB->setChecked(true);
if (lastType != CurveReference::CURVE_REF_DIFF && lastType != CurveReference::CURVE_REF_EXPO) {
lastType = curve.type;
Helpers::populateGVCB(*curveValueCB, curve.value, model);
}
curveValueCB->show();
curveValueSB->hide();
}
else {
curveGVarCB->setChecked(false);
curveValueSB->setMinimum(-100);
curveValueSB->setMaximum(100);
curveValueSB->setValue(curve.value);
curveValueSB->show();
curveValueCB->hide();
}
}
else {
curveGVarCB->hide();
curveValueSB->hide();
curveValueCB->show();
switch (curve.type) {
case CurveReference::CURVE_REF_FUNC:
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i=0; i<=6/*TODO constant*/; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_FUNC, i).toString(&model, false));
}
}
curveValueCB->setCurrentIndex(curve.value);
break;
case CurveReference::CURVE_REF_CUSTOM:
{
int numcurves = getCurrentFirmware()->getCapability(NumCurves);
if (lastType != curve.type) {
lastType = curve.type;
curveValueCB->clear();
for (int i= ((flags & HIDE_NEGATIVE_CURVES) ? 0 : -numcurves); i<=numcurves; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(&model, false), i);
if (i == curve.value) {
curveValueCB->setCurrentIndex(curveValueCB->count() - 1);
}
}
}
break;
}
default:
break;
}
}
lock = false;
}
void CurveGroup::gvarCBChanged(int state)
{
if (!lock) {
if (state) {
curve.value = 10000+1; // TODO constant in EEpromInterface ...
lastType = -1; // quickfix for issue #3518: force refresh of curveValueCB at next update() to set current index to GV1
}
else {
curve.value = 0; // TODO could be better
}
update();
}
}
void CurveGroup::typeChanged(int value)
{
if (!lock) {
int type = curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt();
switch (type) {
case 0:
curve = CurveReference(CurveReference::CURVE_REF_DIFF, 0);
break;
case 1:
curve = CurveReference(CurveReference::CURVE_REF_EXPO, 0);
break;
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, 0);
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, 0);
break;
}
update();
}
}
void CurveGroup::valuesChanged()
{
if (!lock) {
switch (curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt()) {
case 0:
case 1:
{
int value;
if (curveGVarCB->isChecked())
value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt();
else
value = curveValueSB->value();
curve = CurveReference(curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt() == 0 ? CurveReference::CURVE_REF_DIFF : CurveReference::CURVE_REF_EXPO, value);
break;
}
case 2:
curve = CurveReference(CurveReference::CURVE_REF_FUNC, curveValueCB->currentIndex());
break;
case 3:
curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, curveValueCB->itemData(curveValueCB->currentIndex()).toInt());
break;
}
update();
}
}
/*
* Helpers namespace functions
*/
void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
{
int count = getCurrentFirmware()->getCapability(Gvars);
b.clear();
for (int i=-count; i<=-1; i++) {
int16_t gval = (int16_t)(-10000+i);
b.addItem("-" + RawSource(SOURCE_TYPE_GVAR, abs(i)-1).toString(&model), gval);
}
for (int i=1; i<=count; i++) {
int16_t gval = (int16_t)(10000+i);
b.addItem(RawSource(SOURCE_TYPE_GVAR, i-1).toString(&model), gval);
}
b.setCurrentIndex(b.findData(value));
if (b.currentIndex() == -1)
b.setCurrentIndex(count);
}
// Returns Diff/Expo/Weight/Offset adjustment value as either a percentage or a global variable name.
QString Helpers::getAdjustmentString(int16_t val, const ModelData * model, bool sign)
{
QString ret;
if (val >= -10000 && val <= 10000) {
ret = "%1%";
if (sign && val > 0)
ret.prepend("+");
ret = ret.arg(val);
}
else {
ret = RawSource(SOURCE_TYPE_GVAR, abs(val) - 10001).toString(model);
if (val < 0)
ret.prepend("-");
else if (sign)
ret.prepend("+");
}
return ret;
}
// TODO: Move lookup to GVarData class (w/out combobox)
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
{
@@ -742,7 +546,8 @@ GpsCoord extractGpsCoordinates(const QString & position)
return result;
}
TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels)
TableLayout::TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels) :
QObject(parent)
{
#if defined(TABLE_LAYOUT)
tableWidget = new QTableWidget(parent);
+7 -37
View File
@@ -18,8 +18,7 @@
* GNU General Public License for more details.
*/
#ifndef _HELPERS_H_
#define _HELPERS_H_
#pragma once
#include "eeprominterface.h"
#include <QCheckBox>
@@ -60,12 +59,15 @@ class CompanionIcon: public QIcon {
void addImage(const QString &baseimage, Mode mode = Normal, State state = Off);
};
class FilteredItemModel;
class GVarGroup: public QObject {
Q_OBJECT
public:
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true);
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model,
const int deflt, const int mini, const int maxi, const double step = 1.0, FilteredItemModel * gvarModel = nullptr);
void setWeight(int val);
@@ -98,40 +100,9 @@ class GVarGroup: public QObject {
bool lock;
};
#define HIDE_DIFF 0x01
#define HIDE_EXPO 0x02
#define HIDE_NEGATIVE_CURVES 0x04
class CurveGroup : public QObject {
Q_OBJECT
public:
CurveGroup(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QComboBox *curveValueCB, QSpinBox *curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags=0);
void update();
protected slots:
void gvarCBChanged(int);
void typeChanged(int);
void valuesChanged();
protected:
QComboBox *curveTypeCB;
QCheckBox *curveGVarCB;
QComboBox *curveValueCB;
QSpinBox *curveValueSB;
CurveReference & curve;
const ModelData & model;
unsigned int flags;
bool lock;
int lastType;
};
namespace Helpers
{
void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
QString getAdjustmentString(int16_t val, const ModelData * model = NULL, bool sign = false);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
@@ -208,8 +179,9 @@ private:
GpsCoord extractGpsCoordinates(const QString & position);
class TableLayout
class TableLayout: public QObject
{
Q_OBJECT
public:
TableLayout(QWidget * parent, int rowCount, const QStringList & headerLabels);
// ~TableLayout() ;
@@ -263,5 +235,3 @@ private:
};
extern Stopwatch gStopwatch;
#endif // _HELPERS_H_
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Some files were not shown because too many files have changed in this diff Show More