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 "hexinterface.h"
23 #include "firmwareinterface.h"
30 #define VERS_MARK "VERS"
31 #define DATE_MARK "DATE"
32 #define TIME_MARK "TIME"
33 #define EEPR_MARK "EEPR"
34 #define FSIZE_MAX Boards::getFlashSize(Board::BOARD_UNKNOWN)
36 FirmwareInterface::FirmwareInterface(const QString
& filename
):
48 if (!filename
.isEmpty()) {
50 if (file
.open(QIODevice::ReadOnly
| QIODevice::Text
)) { // reading HEX TEXT file
51 QTextStream
inputStream(&file
);
52 flashSize
= HexInterface(inputStream
).load((uint8_t *)flash
.data(), FSIZE_MAX
);
55 file
.open(QIODevice::ReadOnly
);
56 flashSize
= file
.read((char *)flash
.data(), FSIZE_MAX
);
62 flavour
= seekLabel(FW_MARK
);
63 version
= seekLabel(VERS_MARK
);
64 if (version
.startsWith("opentx-")) {
66 int index
= version
.lastIndexOf('-');
67 flavour
= version
.mid(0, index
);
68 version
= version
.mid(index
+1);
70 date
= seekLabel(DATE_MARK
);
71 time
= seekLabel(TIME_MARK
);
72 eepromId
= seekLabel(EEPR_MARK
);
74 if (eepromId
.contains('-')) {
75 QStringList list
= eepromId
.split('-');
76 eepromVersion
= list
[0].toInt();
77 eepromVariant
= list
[1].toInt();
80 eepromVersion
= eepromId
.toInt();
83 versionId
= version2index(version
);
85 isValidFlag
= !version
.isEmpty();
89 QString
FirmwareInterface::seekString(const QString
& string
)
93 int start
= flash
.indexOf(string
);
95 start
+= string
.length();
97 for (int i
=start
; i
<start
+50; i
++) {
99 if (c
== '\0' || c
== '\036') {
105 result
= flash
.mid(start
, (end
- start
)).trimmed();
112 QString
FirmwareInterface::seekLabel(const QString
& label
)
114 QString result
= seekString(label
+ "\037\033:");
115 if (result
.isEmpty()) {
116 result
= seekString(label
+ "\037\075:"); // This is for Horus
118 if (!result
.isEmpty()) {
121 return seekString(label
+ ":");
124 QString
FirmwareInterface::getFlavour() const
126 if (flavour
== "opentx-taranis-x9e")
128 else if (flavour
== "opentx-x9dp" || flavour
== "opentx-taranis-plus")
129 return "opentx-x9d+";
130 else if (flavour
== "opentx-taranis")
132 else if (flavour
== "opentx-horus")
133 return "opentx-x12s";
138 bool FirmwareInterface::isHardwareCompatible(const FirmwareInterface
&previousFirmware
) const
140 QString newFlavour
= getFlavour();
141 if (newFlavour
.isEmpty()) {
144 QString previousFlavour
= previousFirmware
.getFlavour();
145 if (previousFlavour
.isEmpty()) {
148 return (newFlavour
== previousFlavour
);
151 bool FirmwareInterface::seekSplash(QByteArray splash
)
153 int start
= flash
.indexOf(splash
);
155 splashOffset
= start
;
156 splashSize
= splash
.size();
164 bool FirmwareInterface::seekSplash(QByteArray sps
, QByteArray spe
, int size
)
168 start
= flash
.indexOf(sps
, start
+1);
170 int end
= start
+ sps
.size() + size
;
171 if (end
== flash
.indexOf(spe
, end
)) {
172 splashOffset
= start
+ sps
.size();
173 splashSize
= end
- start
- sps
.size();
177 qDebug() << flash
.indexOf(spe
, start
) << end
<< sps
.size() << spe
;
184 #define OTX_SPS_9X "SPS\0\200\100"
185 #define OTX_SPS_TARANIS "SPS\0\324\100"
186 #define OTX_SPS_SIZE 6
187 #define OTX_SPE "SPE"
188 #define OTX_SPE_SIZE 4
190 void FirmwareInterface::seekSplash()
194 splashWidth
= SPLASH_WIDTH
;
195 splashHeight
= SPLASH_HEIGHT
;
196 splash_format
= QImage::Format_Mono
;
198 if (seekSplash(QByteArray((const char *)gr9x_splash
, sizeof(gr9x_splash
))) || seekSplash(QByteArray((const char *)gr9xv4_splash
, sizeof(gr9xv4_splash
)))) {
202 if (seekSplash(QByteArray((const char *)er9x_splash
, sizeof(er9x_splash
)))) {
206 if (seekSplash(QByteArray((const char *)opentx_splash
, sizeof(opentx_splash
)))) {
210 if (seekSplash(QByteArray((const char *)opentxtaranis_splash
, sizeof(opentxtaranis_splash
)))) {
211 splashWidth
= SPLASHX9D_WIDTH
;
212 splashHeight
= SPLASHX9D_HEIGHT
;
213 splash_format
= QImage::Format_Indexed8
;
217 if (seekSplash(QByteArray((const char *)ersky9x_splash
, sizeof(ersky9x_splash
)))) {
221 if (seekSplash(QByteArray(OTX_SPS_9X
, OTX_SPS_SIZE
), QByteArray(OTX_SPE
, OTX_SPE_SIZE
), 1024)) {
225 if (seekSplash(QByteArray(OTX_SPS_TARANIS
, OTX_SPS_SIZE
), QByteArray(OTX_SPE
, OTX_SPE_SIZE
), 6784)) {
226 splashWidth
= SPLASHX9D_WIDTH
;
227 splashHeight
= SPLASHX9D_HEIGHT
;
228 splash_format
= QImage::Format_Indexed8
;
232 if (seekSplash(QByteArray(ERSKY9X_SPS
, sizeof(ERSKY9X_SPS
)), QByteArray(ERSKY9X_SPE
, sizeof(ERSKY9X_SPE
)), 1030)) {
236 if (seekSplash(QByteArray(ERSPLASH_MARKER
, sizeof(ERSPLASH_MARKER
)))) {
237 splashOffset
+= sizeof(ERSPLASH_MARKER
);
238 splashSize
= sizeof(er9x_splash
);
242 bool FirmwareInterface::setSplash(const QImage
& newsplash
)
244 if (splashOffset
== 0 || splashSize
== 0) {
248 char b
[SPLASH_SIZE_MAX
] = {0};
251 if (splash_format
== QImage::Format_Indexed8
) {
252 for (unsigned int y
=0; y
<splashHeight
; y
++) {
253 unsigned int idx
= (y
/2)*splashWidth
;
254 for (unsigned int x
=0; x
<splashWidth
; x
++, idx
++) {
255 QRgb gray
= qGray(newsplash
.pixel(x
, y
));
256 uint8_t z
= ((255-gray
)*15)/255;
263 QColor black
= QColor(0,0,0);
264 QImage blackNwhite
= newsplash
.convertToFormat(QImage::Format_MonoLSB
);
265 for (uint y
=0; y
<splashHeight
; y
++) {
266 for (uint x
=0; x
<splashWidth
; x
++) {
267 color
= QColor(blackNwhite
.pixel(x
,y
));
268 b
[splashWidth
*(y
/8) + x
] |= ((color
==black
? 1: 0)<<(y
% 8));
273 splash
.append(b
, splashSize
);
274 flash
.replace(splashOffset
, splashSize
, splash
);
278 int FirmwareInterface::getSplashWidth()
283 uint
FirmwareInterface::getSplashHeight()
288 QImage::Format
FirmwareInterface::getSplashFormat()
290 return splash_format
;
293 QImage
FirmwareInterface::getSplash()
295 if (splashOffset
== 0 || splashSize
== 0) {
296 return QImage(); // empty image
299 if (splash_format
== QImage::Format_Indexed8
) {
300 QImage
image(splashWidth
, splashHeight
, QImage::Format_RGB888
);
301 if (splashOffset
> 0) {
302 for (unsigned int y
=0; y
<splashHeight
; y
++) {
303 unsigned int idx
= (y
/2)*splashWidth
;
304 for (unsigned int x
=0; x
<splashWidth
; x
++, idx
++) {
305 uint8_t byte
= flash
.at(splashOffset
+idx
);
306 unsigned int z
= (y
& 1) ? (byte
>> 4) : (byte
& 0x0F);
308 QRgb rgb
= qRgb(z
, z
, z
);
309 image
.setPixel(x
, y
, rgb
);
316 QImage
image(splashWidth
, splashHeight
, QImage::Format_Mono
);
317 if (splashOffset
> 0) {
318 for (unsigned int y
=0; y
<splashHeight
; y
++) {
319 for(unsigned int x
=0; x
<splashWidth
; x
++) {
320 image
.setPixel(x
, y
, (flash
.at(splashOffset
+(splashWidth
*(y
/8)+x
)) & (1<<(y
% 8))) ? 0 : 1);
328 bool FirmwareInterface::hasSplash()
330 return (splashOffset
> 0 ? true : false);
333 bool FirmwareInterface::isValid()
338 unsigned int FirmwareInterface::save(const QString
& filename
)
340 uint8_t * binflash
= (uint8_t*)malloc(FSIZE_MAX
);
341 if (binflash
== NULL
) {
344 memcpy(binflash
, flash
.constData(), flashSize
);
345 QFile
file(filename
);
347 int fileType
= getStorageType(filename
);
349 if (fileType
== STORAGE_TYPE_HEX
) {
350 if (!file
.open(QIODevice::ReadWrite
| QIODevice::Truncate
| QIODevice::Text
)) { //reading HEX TEXT file
354 QTextStream
outputStream(&file
);
355 HexInterface hex
=HexInterface(outputStream
);
356 hex
.save(binflash
, flashSize
);
359 if (!file
.open(QIODevice::ReadWrite
| QIODevice::Truncate
)) { //reading HEX TEXT file
363 file
.write((char*)binflash
, flashSize
);