5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "er9xinterface.h"
22 #include "er9xeeprom.h"
24 // #include "appdata.h"
25 // #include <iostream>
28 #define FILE_TYP_GENERAL 1
29 #define FILE_TYP_MODEL 2
31 #define FILE_GENERAL 0
32 #define FILE_MODEL(n) (1+n)
34 Er9xInterface::Er9xInterface():
35 EEPROMInterface(Board::BOARD_STOCK
),
40 Er9xInterface::~Er9xInterface()
45 const char * Er9xInterface::getName()
50 inline void applyStickModeToModel(Er9xModelData
& model
, unsigned int mode
)
52 for (int i
=0; i
<2; i
++) {
53 int stick
= applyStickMode(i
+1, mode
) - 1;
55 int tmp
= model
.trim
[i
];
56 model
.trim
[i
] = model
.trim
[stick
];
57 model
.trim
[stick
] = tmp
;
60 Er9xExpoData tmp
= model
.expoData
[i
];
61 model
.expoData
[i
] = model
.expoData
[stick
];
62 model
.expoData
[stick
] = tmp
;
65 for (int i
=0; i
<ER9X_MAX_MIXERS
; i
++)
66 model
.mixData
[i
].srcRaw
= applyStickMode(model
.mixData
[i
].srcRaw
, mode
);
67 for (int i
=0; i
<ER9X_NUM_CSW
; i
++) {
68 switch (LogicalSwitchData(model
.logicalSw
[i
].func
).getFunctionFamily()) {
70 model
.logicalSw
[i
].v2
= applyStickMode(model
.logicalSw
[i
].v2
, mode
);
73 model
.logicalSw
[i
].v1
= applyStickMode(model
.logicalSw
[i
].v1
, mode
);
79 model
.swashCollectiveSource
= applyStickMode(model
.swashCollectiveSource
, mode
);
83 unsigned long Er9xInterface::loadxml(RadioData
&radioData
, QDomDocument
&doc
)
85 QDebug dbg
= qDebug();
86 dbg
.setAutoInsertSpaces(false);
87 dbg
<< "trying er9x xml import... ";
89 std::bitset
<NUM_ERRORS
> errors
;
91 Er9xGeneral er9xGeneral
;
92 memset(&er9xGeneral
,0,sizeof(er9xGeneral
));
93 if (!loadRadioSettingsDataXML(&doc
, &er9xGeneral
)) {
94 errors
.set(UNKNOWN_ERROR
);
95 return errors
.to_ulong();
98 radioData
.generalSettings
=er9xGeneral
;
99 dbg
<< "version " << (unsigned int)er9xGeneral
.myVers
<< " ";
101 for (int i
=0; i
<getCapability(Models
); i
++) {
102 Er9xModelData er9xModel
;
103 memset(&er9xModel
,0,sizeof(er9xModel
));
104 if(loadModelDataXML(&doc
, &er9xModel
, i
)) {
105 applyStickModeToModel(er9xModel
, radioData
.generalSettings
.stickMode
+1);
106 radioData
.models
[i
] = er9xModel
;
111 return errors
.to_ulong();
115 unsigned long Er9xInterface::load(RadioData
&radioData
, const uint8_t *eeprom
, int size
)
117 QDebug dbg
= qDebug();
118 dbg
.setAutoInsertSpaces(false);
119 dbg
<< "trying er9x import... ";
121 std::bitset
<NUM_ERRORS
> errors
;
123 if (size
!= Boards::getEEpromSize(Board::BOARD_STOCK
)) {
125 errors
.set(WRONG_SIZE
);
126 return errors
.to_ulong();
129 if (!efile
->EeFsOpen((uint8_t *)eeprom
, size
, Board::BOARD_STOCK
)) {
130 dbg
<< "wrong file system";
131 errors
.set(WRONG_FILE_SYSTEM
);
132 return errors
.to_ulong();
135 efile
->openRd(FILE_GENERAL
);
136 Er9xGeneral er9xGeneral
;
138 if (efile
->readRlc1((uint8_t*)&er9xGeneral
, 1) != 1) {
140 errors
.set(UNKNOWN_ERROR
);
141 return errors
.to_ulong();
144 dbg
<< "version " << (unsigned int)er9xGeneral
.myVers
<< " ";
146 switch(er9xGeneral
.myVers
) {
148 dbg
<< "(old gruvin9x) ";
159 errors
.set(NOT_ER9X
);
160 return errors
.to_ulong();
163 efile
->openRd(FILE_GENERAL
);
164 if (!efile
->readRlc1((uint8_t*)&er9xGeneral
, sizeof(Er9xGeneral
))) {
166 errors
.set(UNKNOWN_ERROR
);
167 return errors
.to_ulong();
170 radioData
.generalSettings
= er9xGeneral
;
172 for (int i
=0; i
<getCapability(Models
); i
++) {
173 Er9xModelData er9xModel
;
174 efile
->openRd(FILE_MODEL(i
));
175 if (!efile
->readRlc1((uint8_t*)&er9xModel
, sizeof(Er9xModelData
))) {
176 radioData
.models
[i
].clear();
179 applyStickModeToModel(er9xModel
, radioData
.generalSettings
.stickMode
+1);
180 radioData
.models
[i
] = er9xModel
;
186 return errors
.to_ulong();
189 unsigned long Er9xInterface::loadBackup(RadioData
&radioData
, const uint8_t *eeprom
, int esize
, int index
)
191 std::bitset
<NUM_ERRORS
> errors
;
192 errors
.set(UNKNOWN_ERROR
);
193 return errors
.to_ulong();
196 int Er9xInterface::getSize(const ModelData
&model
)
201 int Er9xInterface::getSize(const GeneralSettings
&settings
)
206 int Er9xInterface::isAvailable(PulsesProtocol prot
, int port
)
219 void Er9xInterface::appendTextElement(QDomDocument
* qdoc
, QDomElement
* pe
, QString name
, QString value
)
221 QDomElement e
= qdoc
->createElement(name
);
222 QDomText t
= qdoc
->createTextNode(name
);
223 t
.setNodeValue(value
);
228 void Er9xInterface::appendNumberElement(QDomDocument
* qdoc
, QDomElement
* pe
,QString name
, int value
, bool forceZeroWrite
)
230 if(value
|| forceZeroWrite
) {
231 QDomElement e
= qdoc
->createElement(name
);
232 QDomText t
= qdoc
->createTextNode(name
);
233 t
.setNodeValue(QString("%1").arg(value
));
239 void Er9xInterface::appendCDATAElement(QDomDocument
* qdoc
, QDomElement
* pe
,QString name
, const char * data
, int size
)
241 QDomElement e
= qdoc
->createElement(name
);
242 QDomCDATASection t
= qdoc
->createCDATASection(name
);
243 t
.setData(QByteArray(data
, size
).toBase64());
248 QDomElement
Er9xInterface::getGeneralDataXML(QDomDocument
* qdoc
, Er9xGeneral
* tgen
)
250 QDomElement gd
= qdoc
->createElement("GENERAL_DATA");
251 appendNumberElement(qdoc
, &gd
, "Version", tgen
->myVers
, true); // have to write value here
252 appendTextElement(qdoc
, &gd
, "Owner", QString::fromLatin1(tgen
->ownerName
,sizeof(tgen
->ownerName
)).trimmed());
253 appendCDATAElement(qdoc
, &gd
, "Data", (const char *)tgen
,sizeof(Er9xGeneral
));
257 QDomElement
Er9xInterface::getModelDataXML(QDomDocument
* qdoc
, Er9xModelData
* tmod
, int modelNum
, int mdver
)
259 QDomElement md
= qdoc
->createElement("MODEL_DATA");
260 md
.setAttribute("number", modelNum
);
261 appendNumberElement(qdoc
, &md
, "Version", mdver
, true); // have to write value here
262 appendTextElement(qdoc
, &md
, "Name", QString::fromLatin1(tmod
->name
,sizeof(tmod
->name
)).trimmed());
263 appendCDATAElement(qdoc
, &md
, "Data", (const char *)tmod
,sizeof(Er9xModelData
));
267 bool Er9xInterface::loadRadioSettingsDataXML(QDomDocument
* qdoc
, Er9xGeneral
* tgen
)
269 // look for "GENERAL_DATA" tag
270 QDomElement gde
= qdoc
->elementsByTagName("GENERAL_DATA").at(0).toElement();
272 if(gde
.isNull()) // couldn't find
275 // load cdata into tgen
276 QDomNode n
= gde
.elementsByTagName("Data").at(0).firstChild();// get all children in Data
277 while (!n
.isNull()) {
278 if (n
.isCDATASection()) {
279 QString ds
= n
.toCDATASection().data();
280 QByteArray ba
= QByteArray::fromBase64(ds
.toLatin1());
281 const char * data
= ba
.data();
282 memcpy(tgen
, data
, sizeof(Er9xGeneral
));
291 bool Er9xInterface::loadModelDataXML(QDomDocument
* qdoc
, Er9xModelData
* tmod
, int modelNum
)
293 // look for MODEL_DATA with modelNum attribute.
294 // if modelNum = -1 then just pick the first one
295 QDomNodeList ndl
= qdoc
->elementsByTagName("MODEL_DATA");
297 // cycle through nodes to find correct model number
298 QDomNode k
= ndl
.at(0);
301 int a
= k
.toElement().attribute("number").toInt();
308 if (k
.isNull()) // couldn't find
312 // load cdata into tgen
313 QDomNode n
= k
.toElement().elementsByTagName("Data").at(0).firstChild();// get all children in Data
314 while (!n
.isNull()) {
315 if (n
.isCDATASection()) {
316 QString ds
= n
.toCDATASection().data();
317 QByteArray ba
= QByteArray::fromBase64(ds
.toLatin1());
318 const char * data
= ba
.data();
319 memcpy(tmod
, data
, sizeof(Er9xModelData
));
328 int Er9xInterface::getCapability(Capability capability
)
330 switch (capability
) {