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 "flasheepromdialog.h"
22 #include "ui_flasheepromdialog.h"
23 #include "eeprominterface.h"
27 #include "progressdialog.h"
28 #include "radiointerface.h"
29 #include "splashlibrarydialog.h"
31 FlashEEpromDialog::FlashEEpromDialog(QWidget
*parent
, const QString
&filename
):
33 ui(new Ui::FlashEEpromDialog
),
34 eepromFilename(filename
)
37 ui
->profileLabel
->setText(tr("Current profile: %1").arg(g
.profile
[g
.id()].name()));
38 if (!filename
.isEmpty()) {
39 ui
->eepromFilename
->hide();
40 ui
->eepromLoad
->hide();
42 QString backupPath
= g
.profile
[g
.id()].pBackupDir();
43 if (backupPath
.isEmpty()) {
44 backupPath
= g
.backupDir();
45 ui
->backupBeforeWrite
->setChecked(g
.enableBackup() || g
.profile
[g
.id()].penableBackup());
47 if (backupPath
.isEmpty() || !QDir(backupPath
).exists()) {
48 ui
->backupBeforeWrite
->setEnabled(false);
52 FlashEEpromDialog::~FlashEEpromDialog()
57 void FlashEEpromDialog::showEvent(QShowEvent
*)
62 void FlashEEpromDialog::updateUI()
64 // ui->burnButton->setEnabled(true);
65 ui
->eepromFilename
->setText(eepromFilename
);
66 if (!eepromFilename
.isEmpty() && getEEpromVersion(eepromFilename
) >= 0) {
67 ui
->profileLabel
->show();
68 ui
->patchCalibration
->show();
69 ui
->patchHardwareSettings
->show();
70 QString name
= g
.profile
[g
.id()].name();
71 QString calib
= g
.profile
[g
.id()].stickPotCalib();
72 QString trainercalib
= g
.profile
[g
.id()].trainerCalib();
73 QString DisplaySet
= g
.profile
[g
.id()].display();
74 QString BeeperSet
= g
.profile
[g
.id()].beeper();
75 QString HapticSet
= g
.profile
[g
.id()].haptic();
76 QString SpeakerSet
= g
.profile
[g
.id()].speaker();
77 if (!name
.isEmpty()) {
78 ui
->profileLabel
->show();
79 ui
->patchCalibration
->show();
80 ui
->patchHardwareSettings
->show();
81 // TODO I hardcode the number of pots here, should be dependant on the board?
82 if (!((calib
.length()==(CPN_MAX_STICKS
+3)*12) && (trainercalib
.length()==16))) {
83 ui
->patchCalibration
->setDisabled(true);
85 if (!((DisplaySet
.length()==6) && (BeeperSet
.length()==4) && (HapticSet
.length()==6) && (SpeakerSet
.length()==6))) {
86 ui
->patchHardwareSettings
->setDisabled(true);
90 ui
->profileLabel
->hide();
92 ui
->burnButton
->setEnabled(true);
95 ui
->profileLabel
->hide();
96 ui
->patchCalibration
->hide();
97 ui
->patchHardwareSettings
->hide();
99 QTimer::singleShot(0, this, SLOT(shrink()));
102 void FlashEEpromDialog::on_eepromLoad_clicked()
104 QString filename
= QFileDialog::getOpenFileName(this, tr("Choose Radio Backup file"), g
.eepromDir(), EXTERNAL_EEPROM_FILES_FILTER
);
105 if (!filename
.isEmpty()) {
106 eepromFilename
= filename
;
111 int FlashEEpromDialog::getEEpromVersion(const QString
& filename
)
114 QSharedPointer
<RadioData
> radioData
= QSharedPointer
<RadioData
>(new RadioData());
115 Storage
storage(filename
);
116 if (storage
.load(*radioData
)) {
117 result
= radioData
->generalSettings
.version
;
120 QMessageBox::warning(this, CPN_STR_TTL_ERROR
, storage
.error());
125 bool FlashEEpromDialog::patchCalibration(RadioData
* radioData
)
127 QString calib
= g
.profile
[g
.id()].stickPotCalib();
128 QString trainercalib
= g
.profile
[g
.id()].trainerCalib();
129 int potsnum
= getBoardCapability(getCurrentBoard(), Board::Pots
);
130 int8_t txVoltageCalibration
= (int8_t) g
.profile
[g
.id()].txVoltageCalibration();
131 int8_t txCurrentCalibration
= (int8_t) g
.profile
[g
.id()].txCurrentCalibration();
132 int8_t PPM_Multiplier
= (int8_t) g
.profile
[g
.id()].ppmMultiplier();
134 if ((calib
.length()==(CPN_MAX_STICKS
+potsnum
)*12) && (trainercalib
.length()==16)) {
138 for (int i
=0; i
<CPN_MAX_STICKS
+potsnum
; i
++) {
139 Byte
=calib
.mid(i
*12,4);
140 byte16
=(int16_t)Byte
.toInt(&ok
,16);
142 radioData
->generalSettings
.calibMid
[i
]=byte16
;
143 Byte
=calib
.mid(4+i
*12,4);
144 byte16
=(int16_t)Byte
.toInt(&ok
,16);
146 radioData
->generalSettings
.calibSpanNeg
[i
]=byte16
;
147 Byte
=calib
.mid(8+i
*12,4);
148 byte16
=(int16_t)Byte
.toInt(&ok
,16);
150 radioData
->generalSettings
.calibSpanPos
[i
]=byte16
;
152 for (int i
=0; i
<4; i
++) {
153 Byte
= trainercalib
.mid(i
*4,4);
154 byte16
= (int16_t)Byte
.toInt(&ok
,16);
156 radioData
->generalSettings
.trainer
.calib
[i
] = byte16
;
159 radioData
->generalSettings
.txCurrentCalibration
= txCurrentCalibration
;
160 radioData
->generalSettings
.txVoltageCalibration
= txVoltageCalibration
;
161 radioData
->generalSettings
.PPM_Multiplier
= PPM_Multiplier
;
165 QMessageBox::critical(this, CPN_STR_TTL_WARNING
, tr("Wrong radio calibration data in profile, Settings not patched"));
170 bool FlashEEpromDialog::patchHardwareSettings(RadioData
* radioData
)
172 QString DisplaySet
= g
.profile
[g
.id()].display();
173 QString BeeperSet
= g
.profile
[g
.id()].beeper();
174 QString HapticSet
= g
.profile
[g
.id()].haptic();
175 QString SpeakerSet
= g
.profile
[g
.id()].speaker();
176 uint8_t GSStickMode
=(uint8_t) g
.profile
[g
.id()].gsStickMode();
177 uint8_t vBatWarn
=(uint8_t) g
.profile
[g
.id()].vBatWarn();
179 if ((DisplaySet
.length()==6) && (BeeperSet
.length()==4) && (HapticSet
.length()==6) && (SpeakerSet
.length()==6)) {
180 radioData
->generalSettings
.vBatWarn
= vBatWarn
;
181 radioData
->generalSettings
.stickMode
= GSStickMode
;
185 byte8
=(int8_t)DisplaySet
.mid(0,2).toInt(&ok
,16);
186 if (ok
) radioData
->generalSettings
.optrexDisplay
=(byte8
==1 ? true : false);
187 byte8u
=(uint8_t)DisplaySet
.mid(2,2).toUInt(&ok
,16);
188 if (ok
) radioData
->generalSettings
.contrast
=byte8u
;
189 byte8u
=(uint8_t)DisplaySet
.mid(4,2).toUInt(&ok
,16);
190 if (ok
) radioData
->generalSettings
.backlightBright
=byte8u
;
191 byte8u
=(uint8_t)BeeperSet
.mid(0,2).toUInt(&ok
,16);
192 if (ok
) radioData
->generalSettings
.beeperMode
=(GeneralSettings::BeeperMode
)byte8u
;
193 byte8
=(int8_t)BeeperSet
.mid(2,2).toInt(&ok
,16);
194 if (ok
) radioData
->generalSettings
.beeperLength
=byte8
;
195 byte8u
=(uint8_t)HapticSet
.mid(0,2).toUInt(&ok
,16);
196 if (ok
) radioData
->generalSettings
.hapticMode
=(GeneralSettings::BeeperMode
)byte8u
;
197 byte8u
=(uint8_t)HapticSet
.mid(2,2).toUInt(&ok
,16);
198 if (ok
) radioData
->generalSettings
.hapticStrength
=byte8u
;
199 byte8
=(int8_t)HapticSet
.mid(4,2).toInt(&ok
,16);
200 if (ok
) radioData
->generalSettings
.hapticLength
=byte8
;
201 byte8u
=(uint8_t)SpeakerSet
.mid(0,2).toUInt(&ok
,16);
202 if (ok
) radioData
->generalSettings
.speakerMode
=byte8u
;
203 byte8u
=(uint8_t)SpeakerSet
.mid(2,2).toUInt(&ok
,16);
204 if (ok
) radioData
->generalSettings
.speakerPitch
=byte8u
;
205 byte8u
=(uint8_t)SpeakerSet
.mid(4,2).toUInt(&ok
,16);
206 if (ok
) radioData
->generalSettings
.speakerVolume
=byte8u
;
210 QMessageBox::critical(this, CPN_STR_TTL_WARNING
, tr("Wrong radio setting data in profile, Settings not patched"));
215 void FlashEEpromDialog::on_burnButton_clicked()
217 QString filename
= eepromFilename
;
220 if (ui
->patchCalibration
->isChecked() || ui
->patchHardwareSettings
->isChecked()) {
221 QSharedPointer
<RadioData
> radioData
= QSharedPointer
<RadioData
>(new RadioData());
222 Storage
storage(eepromFilename
);
223 if (storage
.load(*radioData
)) {
224 if (ui
->patchCalibration
->isChecked())
225 patch
|= patchCalibration(radioData
.data());
226 if (ui
->patchHardwareSettings
->isChecked())
227 patch
|= patchHardwareSettings(radioData
.data());
231 filename
= generateProcessUniqueTempFileName("patched.bin");
232 QFile
file(filename
);
233 uint8_t *eeprom
= (uint8_t*)malloc(Boards::getEEpromSize(getCurrentBoard()));
234 int eeprom_size
= getCurrentEEpromInterface()->save(eeprom
, *radioData
, 0, getCurrentFirmware()->getVariantNumber());
235 if (eeprom_size
== 0) {
238 if (!file
.open(QIODevice::WriteOnly
)) {
239 QMessageBox::warning(this, CPN_STR_TTL_ERROR
, tr("Cannot write file %1:\n%2.").arg(filename
).arg(file
.errorString()));
242 QTextStream
outputStream(&file
);
243 long result
= file
.write((char*)eeprom
, eeprom_size
);
244 if (result
!= eeprom_size
) {
245 QMessageBox::warning(this, CPN_STR_TTL_ERROR
, tr("Error writing file %1:\n%2.").arg(filename
).arg(file
.errorString()));
253 ProgressDialog
progressDialog(this, tr("Write Models and Settings to Radio"), CompanionIcon("write_eeprom.png"));
255 // backup previous EEPROM if requested
256 QString backupFilename
;
258 if (ui
->backupBeforeWrite
->isChecked()) {
259 backupPath
= g
.profile
[g
.id()].pBackupDir();
260 if (backupPath
.isEmpty()) {
261 backupPath
=g
.backupDir();
263 backupFilename
= backupPath
+ "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
265 else if (ui
->checkFirmwareCompatibility
->isChecked()) {
266 backupFilename
= generateProcessUniqueTempFileName("eeprom.bin");
268 if (!backupFilename
.isEmpty()) {
269 if (!readEeprom(backupFilename
, progressDialog
.progress())) {
274 // check EEPROM compatibility if requested
275 if (ui
->checkFirmwareCompatibility
->isChecked()) {
276 int eepromVersion
= getEEpromVersion(filename
);
277 QString firmwareFilename
= generateProcessUniqueTempFileName("flash.bin");
278 if (!readFirmware(firmwareFilename
, progressDialog
.progress()))
280 QString compatEEprom
= generateProcessUniqueTempFileName("compat.bin");
281 if (convertEEprom(filename
, compatEEprom
, firmwareFilename
)) {
282 int compatVersion
= getEEpromVersion(compatEEprom
);
283 if ((compatVersion
/ 100) != (eepromVersion
/ 100)) {
284 QMessageBox::warning(this, CPN_STR_TTL_WARNING
, tr("The radio firmware belongs to another product family, check file and preferences!"));
287 else if (compatVersion
< eepromVersion
) {
288 QMessageBox::warning(this, CPN_STR_TTL_WARNING
, tr("The radio firmware is outdated, please upgrade!"));
291 filename
= compatEEprom
;
293 else if (QMessageBox::question(this, CPN_STR_TTL_ERROR
, tr("Cannot check Models and Settings compatibility! Continue anyway?"), QMessageBox::Yes
|QMessageBox::No
) == QMessageBox::No
) {
296 qunlink(firmwareFilename
);
300 bool result
= writeEeprom(filename
, progressDialog
.progress());
301 if (!result
&& !progressDialog
.isEmpty()) {
302 progressDialog
.exec();
306 void FlashEEpromDialog::on_cancelButton_clicked()
311 void FlashEEpromDialog::shrink()