2 * Author - Bertrand Songis <bsongis@gmail.com>
4 * Based on th9x -> http://code.google.com/p/th9x/
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #include "hexinterface.h"
20 #include "firmwareinterface.h"
24 #define VERS_MARK "VERS"
25 #define DATE_MARK "DATE"
26 #define TIME_MARK "TIME"
27 #define EEPR_MARK "EEPR"
29 int getFileType(const QString
&fullFileName
)
31 QString suffix
= QFileInfo(fullFileName
).suffix().toUpper();
34 else if (suffix
== "BIN")
36 else if (suffix
== "EEPM")
37 return FILE_TYPE_EEPM
;
38 else if (suffix
== "EEPE")
39 return FILE_TYPE_EEPE
;
40 else if (suffix
== "XML")
46 FirmwareInterface::FirmwareInterface(const QString
&filename
):
58 if (!filename
.isEmpty()) {
60 if (file
.open(QIODevice::ReadOnly
| QIODevice::Text
)) { // reading HEX TEXT file
61 QTextStream
inputStream(&file
);
62 flashSize
= HexInterface(inputStream
).load((uint8_t *)flash
.data(), MAX_FSIZE
);
65 file
.open(QIODevice::ReadOnly
);
66 flashSize
= file
.read((char *)flash
.data(), MAX_FSIZE
);
72 flavour
= seekLabel(FW_MARK
);
73 version
= seekLabel(VERS_MARK
);
74 if (version
.startsWith("opentx-")) {
76 int index
= version
.lastIndexOf('-');
77 flavour
= version
.mid(0, index
);
78 version
= version
.mid(index
+1);
80 date
= seekLabel(DATE_MARK
);
81 time
= seekLabel(TIME_MARK
);
82 eepromId
= seekLabel(EEPR_MARK
);
84 if (eepromId
.contains('-')) {
85 QStringList list
= eepromId
.split('-');
86 eepromVersion
= list
[0].toInt();
87 eepromVariant
= list
[1].toInt();
90 eepromVersion
= eepromId
.toInt();
93 versionId
= version2index(version
);
95 isValidFlag
= !version
.isEmpty();
99 QString
FirmwareInterface::seekString(const QString
& string
)
103 int start
= flash
.indexOf(string
);
105 start
+= string
.length();
107 for (int i
=start
; i
<start
+50; i
++) {
108 char c
= flash
.at(i
);
109 if (c
== '\0' || c
== '\036') {
115 result
= flash
.mid(start
, (end
- start
)).trimmed();
122 QString
FirmwareInterface::seekLabel(const QString
& label
)
124 QString result
= seekString(label
+ "\037\033:");
125 if (!result
.isEmpty())
128 return seekString(label
+ ":");
131 QString
FirmwareInterface::getFlavour() const
133 if (flavour
== "opentx-x9dp")
134 return "opentx-taranis-plus";
135 else if (flavour
== "opentx-x9d")
136 return "opentx-taranis";
141 bool FirmwareInterface::isHardwareCompatible(const FirmwareInterface
&previousFirmware
) const
143 QString newFlavour
= getFlavour();
144 if (newFlavour
.isEmpty())
147 QString previousFlavour
= previousFirmware
.getFlavour();
148 if (previousFlavour
.isEmpty())
151 return (newFlavour
== previousFlavour
);
154 bool FirmwareInterface::SeekSplash(QByteArray splash
)
156 int start
= flash
.indexOf(splash
);
158 splashOffset
= start
;
159 splashSize
= splash
.size();
167 bool FirmwareInterface::SeekSplash(QByteArray sps
, QByteArray spe
, int size
)
171 start
= flash
.indexOf(sps
, start
+1);
173 int end
= start
+ sps
.size() + size
;
174 if (end
== flash
.indexOf(spe
, end
)) {
175 splashOffset
= start
+ sps
.size();
176 splashSize
= end
- start
- sps
.size();
180 qDebug() << flash
.indexOf(spe
, start
) << end
<< sps
.size() << spe
;
187 #define OTX_SPS_9X "SPS\0\200\100"
188 #define OTX_SPS_TARANIS "SPS\0\324\100"
189 #define OTX_SPS_SIZE 6
190 #define OTX_SPE "SPE"
191 #define OTX_SPE_SIZE 4
193 void FirmwareInterface::SeekSplash(void)
197 splashWidth
= SPLASH_WIDTH
;
198 splashHeight
= SPLASH_HEIGHT
;
199 splash_format
= QImage::Format_Mono
;
201 if (SeekSplash(QByteArray((const char *)gr9x_splash
, sizeof(gr9x_splash
))) || SeekSplash(QByteArray((const char *)gr9xv4_splash
, sizeof(gr9xv4_splash
)))) {
205 if (SeekSplash(QByteArray((const char *)er9x_splash
, sizeof(er9x_splash
)))) {
209 if (SeekSplash(QByteArray((const char *)opentx_splash
, sizeof(opentx_splash
)))) {
213 if (SeekSplash(QByteArray((const char *)opentxtaranis_splash
, sizeof(opentxtaranis_splash
)))) {
214 splashWidth
= SPLASHX9D_WIDTH
;
215 splashHeight
= SPLASHX9D_HEIGHT
;
216 splash_format
= QImage::Format_Indexed8
;
220 if (SeekSplash(QByteArray((const char *)ersky9x_splash
, sizeof(ersky9x_splash
)))) {
224 if (SeekSplash(QByteArray(OTX_SPS_9X
, OTX_SPS_SIZE
), QByteArray(OTX_SPE
, OTX_SPE_SIZE
), 1024)) {
228 if (SeekSplash(QByteArray(OTX_SPS_TARANIS
, OTX_SPS_SIZE
), QByteArray(OTX_SPE
, OTX_SPE_SIZE
), 6784)) {
229 splashWidth
= SPLASHX9D_WIDTH
;
230 splashHeight
= SPLASHX9D_HEIGHT
;
231 splash_format
= QImage::Format_Indexed8
;
235 if (SeekSplash(QByteArray(ERSKY9X_SPS
, sizeof(ERSKY9X_SPS
)), QByteArray(ERSKY9X_SPE
, sizeof(ERSKY9X_SPE
)), 1030)) {
239 if (SeekSplash(QByteArray(ERSPLASH_MARKER
, sizeof(ERSPLASH_MARKER
)))) {
240 splashOffset
+= sizeof(ERSPLASH_MARKER
);
241 splashSize
= sizeof(er9x_splash
);
245 bool FirmwareInterface::setSplash(const QImage
& newsplash
)
247 if (splashOffset
== 0 || splashSize
== 0) {
251 char b
[SPLASH_SIZE_MAX
] = {0};
254 if (splash_format
== QImage::Format_Indexed8
) {
255 for (unsigned int y
=0; y
<splashHeight
; y
++) {
256 unsigned int idx
= (y
/2)*splashWidth
;
257 for (unsigned int x
=0; x
<splashWidth
; x
++, idx
++) {
258 QRgb gray
= qGray(newsplash
.pixel(x
, y
));
259 uint8_t z
= ((255-gray
)*15)/255;
266 QColor black
= QColor(0,0,0);
267 QImage blackNwhite
= newsplash
.convertToFormat(QImage::Format_MonoLSB
);
268 for (uint y
=0; y
<splashHeight
; y
++) {
269 for (uint x
=0; x
<splashWidth
; x
++) {
270 color
= QColor(blackNwhite
.pixel(x
,y
));
271 b
[splashWidth
*(y
/8) + x
] |= ((color
==black
? 1: 0)<<(y
% 8));
276 splash
.append(b
, splashSize
);
277 flash
.replace(splashOffset
, splashSize
, splash
);
281 int FirmwareInterface::getSplashWidth()
286 uint
FirmwareInterface::getSplashHeight()
291 QImage::Format
FirmwareInterface::getSplashFormat()
293 return splash_format
;
296 QImage
FirmwareInterface::getSplash()
298 if (splashOffset
== 0 || splashSize
== 0) {
299 return QImage(); // empty image
302 if (splash_format
== QImage::Format_Indexed8
) {
303 QImage
image(splashWidth
, splashHeight
, QImage::Format_RGB888
);
304 if (splashOffset
> 0) {
305 for (unsigned int y
=0; y
<splashHeight
; y
++) {
306 unsigned int idx
= (y
/2)*splashWidth
;
307 for (unsigned int x
=0; x
<splashWidth
; x
++, idx
++) {
308 uint8_t byte
= flash
.at(splashOffset
+idx
);
309 unsigned int z
= (y
& 1) ? (byte
>> 4) : (byte
& 0x0F);
311 QRgb rgb
= qRgb(z
, z
, z
);
312 image
.setPixel(x
, y
, rgb
);
319 QImage
image(splashWidth
, splashHeight
, QImage::Format_Mono
);
320 if (splashOffset
> 0) {
321 for (unsigned int y
=0; y
<splashHeight
; y
++) {
322 for(unsigned int x
=0; x
<splashWidth
; x
++) {
323 image
.setPixel(x
, y
, (flash
.at(splashOffset
+(splashWidth
*(y
/8)+x
)) & (1<<(y
% 8))) ? 0 : 1);
331 bool FirmwareInterface::hasSplash()
333 return (splashOffset
> 0 ? true : false);
336 bool FirmwareInterface::isValid()
341 unsigned int FirmwareInterface::save(QString fileName
)
343 uint8_t binflash
[MAX_FSIZE
];
344 memcpy(&binflash
, flash
.constData(), flashSize
);
345 QFile
file(fileName
);
347 int fileType
= getFileType(fileName
);
349 if (fileType
== FILE_TYPE_HEX
) {
350 if (!file
.open(QIODevice::ReadWrite
| QIODevice::Truncate
| QIODevice::Text
)) { //reading HEX TEXT file
353 QTextStream
outputStream(&file
);
354 HexInterface hex
=HexInterface(outputStream
);
355 hex
.save(binflash
, flashSize
);
358 if (!file
.open(QIODevice::ReadWrite
| QIODevice::Truncate
)) { //reading HEX TEXT file
361 file
.write((char*)binflash
, flashSize
);