comparison OSTC3Operations.cpp @ 8:21ce6187d32e

Minor changes done by automatic style checker
author Ideenmodellierer
date Mon, 12 Jan 2026 13:51:17 +0000
parents 115cfa4a3239
children
comparison
equal deleted inserted replaced
7:0969ef86c42d 8:21ce6187d32e
38 38
39 #include "Utils/Exception.h" 39 #include "Utils/Exception.h"
40 #include "Utils/Log.h" 40 #include "Utils/Log.h"
41 #include "Utils/ProgressEvent.h" 41 #include "Utils/ProgressEvent.h"
42 42
43 #include "HexFile.h"
43 #include "SettingsDialog.h" 44 #include "SettingsDialog.h"
44 #include "HexFile.h"
45 45
46 #include <QApplication> 46 #include <QApplication>
47 #include <QDateTime> 47 #include <QDateTime>
48 #include <QDir> 48 #include <QDir>
49 #include <QRegularExpression> 49 #include <QRegularExpression>
50 50
51 // Byte extration, compatible littleendian or bigendian. 51 // Byte extration, compatible littleendian or bigendian.
52 #define LOW(x) ((unsigned char)((x) % 256)) 52 #define LOW(x) ((unsigned char) ((x) % 256))
53 #define HIGH(x) ((unsigned char)((x / (1<<8)) % 256)) 53 #define HIGH(x) ((unsigned char) ((x / (1 << 8)) % 256))
54 #define UPPER(x) ((unsigned char)((x / (1<<16)) % 256)) 54 #define UPPER(x) ((unsigned char) ((x / (1 << 16)) % 256))
55 #define UP32(x) ((unsigned char)((x / (1<<24)) % 256)) 55 #define UP32(x) ((unsigned char) ((x / (1 << 24)) % 256))
56 56
57 #define FIRMWARE_AREA 0x3E0000 57 #define FIRMWARE_AREA 0x3E0000
58 #define FIRMWARE_SIZE 0x01E000 // 120KB 58 #define FIRMWARE_SIZE 0x01E000 // 120KB
59 #define FIRMWARE_BLOCK 0x1000 // 4KB 59 #define FIRMWARE_BLOCK 0x1000 // 4KB
60 60
61 ////////////////////////////////////////////////////////////////////////////// 61 //////////////////////////////////////////////////////////////////////////////
62 62
63 OSTC3Operations::OSTC3Operations() 63 OSTC3Operations::OSTC3Operations()
64 : descriptionString(""), 64 : descriptionString("")
65 emulatorName("OSTC3"), 65 , emulatorName("OSTC3")
66 _computerFirmware(0), 66 , _computerFirmware(0)
67 _computerSerial(0), 67 , _computerSerial(0)
68 _connectMode(CLOSED_MODE) 68 , _connectMode(CLOSED_MODE)
69 { 69 {
70 memset(computerText, 0, sizeof computerText); 70 memset(computerText, 0, sizeof computerText);
71 } 71 }
72 72
73 OSTC3Operations::~OSTC3Operations() 73 OSTC3Operations::~OSTC3Operations()
74 { 74 {
75 if( _connectMode != CLOSED_MODE ) 75 if (_connectMode != CLOSED_MODE)
76 disconnect(true); 76 disconnect(true);
77 } 77 }
78 78
79 ////////////////////////////////////////////////////////////////////////////// 79 //////////////////////////////////////////////////////////////////////////////
80 80
85 85
86 ////////////////////////////////////////////////////////////////////////////// 86 //////////////////////////////////////////////////////////////////////////////
87 87
88 bool OSTC3Operations::connect() 88 bool OSTC3Operations::connect()
89 { 89 {
90 LOG_TRACE( "Enter download mode..." ); 90 LOG_TRACE("Enter download mode...");
91 91
92 try { 92 try {
93 _connectMode = CLOSED_MODE; 93 _connectMode = CLOSED_MODE;
94 _serial.open( Settings::port, emulatorName); 94 _serial.open(Settings::port, emulatorName);
95 _serial.sleep(333); // Initial 1/3 sec. delay to first comm. 95 _serial.sleep(333); // Initial 1/3 sec. delay to first comm.
96 96
97 for(int retry=0; retry < 10; ++retry) 97 for (int retry = 0; retry < 10; ++retry) {
98 {
99 // Allow for 0.1sec extra delay 98 // Allow for 0.1sec extra delay
100 try { 99 try {
101 _serial.writeByte(0xBB); 100 _serial.writeByte(0xBB);
102 } catch(const WriteTimeout& ) { 101 } catch (const WriteTimeout &) {
103 // Bluetooth not present: one can open the pseudo COM port, 102 // Bluetooth not present: one can open the pseudo COM port,
104 // but we will have a timeout on first write byte... 103 // but we will have a timeout on first write byte...
105 if( retry < 9 ) { 104 if (retry < 9) {
106 LOG_INFO("Cannot connect to " << Settings::port <<" (" << (retry+1) << "/10)..."); 105 LOG_INFO("Cannot connect to " << Settings::port << " (" << (retry + 1)
106 << "/10)...");
107 _serial.sleep(1000); 107 _serial.sleep(1000);
108 continue; 108 continue;
109 } 109 }
110 LOG_THROW("Cannot connect to " << model() <<"."); 110 LOG_THROW("Cannot connect to " << model() << ".");
111 return false; 111 return false;
112 } 112 }
113 113
114 _serial.sleep(100); 114 _serial.sleep(100);
115 115
116 //---- Check acknowledge, w/o fatal timeouts. 116 //---- Check acknowledge, w/o fatal timeouts.
117 unsigned char ok = 0; 117 unsigned char ok = 0;
118 unsigned char echo = 0; 118 unsigned char echo = 0;
119 try { 119 try {
120 echo = _serial.readByte(); 120 echo = _serial.readByte();
121 121
122 // Already in connect() mode ??? 122 // Already in connect() mode ???
123 if( echo == 'M' ) 123 if (echo == 'M')
124 break; 124 break;
125 125
126 ok = _serial.readByte(); 126 ok = _serial.readByte();
127 } catch (const ReadTimeout &) {
128 LOG_INFO("Retry " << (retry + 1) << "/10...");
127 } 129 }
128 catch(const ReadTimeout&) { 130
129 LOG_INFO("Retry " << (retry+1) << "/10..."); 131 if (echo != 0xBB || ok != 0x4D) { // DOWNLOAD modes only.
130 } 132 if (retry < 9) {
131
132 if( echo != 0xBB || ok != 0x4D ) { // DOWNLOAD modes only.
133 if( retry < 9 )
134 {
135 _serial.purge(); 133 _serial.purge();
136 _serial.sleep(400); 134 _serial.sleep(400);
137 continue; 135 continue;
138 } 136 }
139 LOG_THROW("Unable to enter hwOS service mode"); 137 LOG_THROW("Unable to enter hwOS service mode");
146 QString banner = Log::applicationName(); 144 QString banner = Log::applicationName();
147 writeText(banner); 145 writeText(banner);
148 LOG_TRACE("Connected."); 146 LOG_TRACE("Connected.");
149 _connectMode = DOWNLOAD_MODE; 147 _connectMode = DOWNLOAD_MODE;
150 return true; 148 return true;
151 } 149 } catch (const Exception &e) {
152 catch(const Exception& e) {
153 disconnect(); 150 disconnect();
154 LOG_THROW("Port " << Settings::port << ": " << e.what()); 151 LOG_THROW("Port " << Settings::port << ": " << e.what());
155 } 152 }
156 return false; 153 return false;
157 } 154 }
158 155
159 ////////////////////////////////////////////////////////////////////////////// 156 //////////////////////////////////////////////////////////////////////////////
160 157
161 bool OSTC3Operations::disconnect(bool /*closing*/) 158 bool OSTC3Operations::disconnect(bool /*closing*/)
162 { 159 {
163 if( _connectMode == CLOSED_MODE ) return false; 160 if (_connectMode == CLOSED_MODE)
164 161 return false;
165 descriptionString.clear(); // cleanup for interface updateStatus() 162
163 descriptionString.clear(); // cleanup for interface updateStatus()
166 _connectMode = CLOSED_MODE; 164 _connectMode = CLOSED_MODE;
167 165
168 _serial.purge(); 166 _serial.purge();
169 _serial.writeByte(0xFF); // Exit communications, just in case... 167 _serial.writeByte(0xFF); // Exit communications, just in case...
170 _serial.sleep(100); 168 _serial.sleep(100);
171 169
172 _serial.purge(); 170 _serial.purge();
173 _serial.close(); 171 _serial.close();
174 172
181 { 179 {
182 descriptionString.clear(); 180 descriptionString.clear();
183 181
184 LOG_TRACE("Getting model..."); 182 LOG_TRACE("Getting model...");
185 HardwareDescriptor hw = hardwareDescriptor(); 183 HardwareDescriptor hw = hardwareDescriptor();
186 // if( hw != HW_OSTC3 ) 184 // if( hw != HW_OSTC3 )
187 // LOG_THROW("Not an OSTC3."); 185 // LOG_THROW("Not an OSTC3.");
188 186
189 LOG_TRACE("Getting identity..."); 187 LOG_TRACE("Getting identity...");
190 getCommonIdentity(); 188 getCommonIdentity();
191 189
192 LOG_INFO("Found " << descriptionString.trimmed()); 190 LOG_INFO("Found " << descriptionString.trimmed());
195 ////////////////////////////////////////////////////////////////////////////// 193 //////////////////////////////////////////////////////////////////////////////
196 194
197 void OSTC3Operations::getCommonIdentity() 195 void OSTC3Operations::getCommonIdentity()
198 { 196 {
199 unsigned char echo = retryCommand(_serial, 'i'); // 0x69 197 unsigned char echo = retryCommand(_serial, 'i'); // 0x69
200 if( echo != 'i' ) 198 if (echo != 'i')
201 LOG_THROW("Bad identity reply (1)"); 199 LOG_THROW("Bad identity reply (1)");
202 200
203 unsigned char header[4 + 60 + 1] = {0}; 201 unsigned char header[4 + 60 + 1] = {0};
204 _serial.readBlock(header, sizeof header); 202 _serial.readBlock(header, sizeof header);
205 if( header[64] != 0x4D ) // DOWNLOAD modes only. 203 if (header[64] != 0x4D) // DOWNLOAD modes only.
206 LOG_THROW("Bad identity reply (2)"); 204 LOG_THROW("Bad identity reply (2)");
207 205
208 _computerSerial = header[0] + header[1]*256; 206 _computerSerial = header[0] + header[1] * 256;
209 _computerFirmware = header[2] * 100 + header[3]; 207 _computerFirmware = header[2] * 100 + header[3];
210 memcpy(computerText, header+4, sizeof computerText); 208 memcpy(computerText, header + 4, sizeof computerText);
211 209
212 descriptionString = QString("%1 #%2, fw %3.%4, %5") 210 descriptionString
213 .arg(model()) 211 = QString("%1 #%2, fw %3.%4, %5")
214 .arg(serialNumber(), 4, 10, QChar('0')) 212 .arg(model())
215 .arg(firmware() / 100).arg(firmware() % 100, 2, 10, QChar('0')) 213 .arg(serialNumber(), 4, 10, QChar('0'))
216 .arg( QString::fromLatin1((char*)(computerText), 60) 214 .arg(firmware() / 100)
217 .replace(QChar('\0'), " ") ); 215 .arg(firmware() % 100, 2, 10, QChar('0'))
216 .arg(QString::fromLatin1((char *) (computerText), 60).replace(QChar('\0'), " "));
218 } 217 }
219 218
220 ////////////////////////////////////////////////////////////////////////////// 219 //////////////////////////////////////////////////////////////////////////////
221 220
222 int OSTC3Operations::firmware() const 221 int OSTC3Operations::firmware() const
241 return QSize(12, 5); 240 return QSize(12, 5);
242 } 241 }
243 242
244 ////////////////////////////////////////////////////////////////////////////// 243 //////////////////////////////////////////////////////////////////////////////
245 244
246 void OSTC3Operations::writeText(const QString& msg) 245 void OSTC3Operations::writeText(const QString &msg)
247 { 246 {
248 QByteArray buffer = msg.leftJustified(16, ' ', true).toLatin1(); 247 QByteArray buffer = msg.leftJustified(16, ' ', true).toLatin1();
249 LOG_TRACE("Echoing string '" << buffer << "'"); 248 LOG_TRACE("Echoing string '" << buffer << "'");
250 249
251 // 2014-10-27 jDG: On OSTC3 v1.60, after an ERASE AREA, we do get 250 // 2014-10-27 jDG: On OSTC3 v1.60, after an ERASE AREA, we do get
252 // a spurious L here (instead of n)... 251 // a spurious L here (instead of n)...
253 unsigned char echo = retryCommand(_serial, 'n'); // 0x6E Echo string. 252 unsigned char echo = retryCommand(_serial, 'n'); // 0x6E Echo string.
254 if( echo != 'n' ) 253 if (echo != 'n')
255 LOG_THROW("Bad message reply (1)"); 254 LOG_THROW("Bad message reply (1)");
256 255
257 _serial.writeBlock((const unsigned char*)buffer.data(), 16); 256 _serial.writeBlock((const unsigned char *) buffer.data(), 16);
258 _serial.sleep(25); // Allow 25msec to display the message... 257 _serial.sleep(25); // Allow 25msec to display the message...
259 258
260 unsigned char ok = _serial.readByte(); 259 unsigned char ok = _serial.readByte();
261 if( ok != 0x4C && ok != 0x4D ) // DOWNLOAD or SERVICE modes. 260 if (ok != 0x4C && ok != 0x4D) // DOWNLOAD or SERVICE modes.
262 LOG_THROW("Bad message reply (2)"); 261 LOG_THROW("Bad message reply (2)");
263 } 262 }
264 263
265 ////////////////////////////////////////////////////////////////////////////// 264 //////////////////////////////////////////////////////////////////////////////
266 265
275 buffer[3] = date.date().month(); 274 buffer[3] = date.date().month();
276 buffer[4] = date.date().day(); 275 buffer[4] = date.date().day();
277 buffer[5] = date.date().year() % 100; 276 buffer[5] = date.date().year() % 100;
278 277
279 unsigned char echo = retryCommand(_serial, 'b'); // 0x62 Sync date 278 unsigned char echo = retryCommand(_serial, 'b'); // 0x62 Sync date
280 if( echo != 'b' ) 279 if (echo != 'b')
281 LOG_THROW("Bad clock reply (1)"); 280 LOG_THROW("Bad clock reply (1)");
282 281
283 _serial.writeBlock(buffer, sizeof buffer); 282 _serial.writeBlock(buffer, sizeof buffer);
284 _serial.sleep(5); 283 _serial.sleep(5);
285 284
286 unsigned char ok = _serial.readByte(); 285 unsigned char ok = _serial.readByte();
287 if( ok != 0x4D ) // DOWNLOAD mode only. 286 if (ok != 0x4D) // DOWNLOAD mode only.
288 LOG_THROW("Bad clock reply (2)"); 287 LOG_THROW("Bad clock reply (2)");
289 288
290 writeText( "Set " + date.toString("MM/dd hh:mm") ); 289 writeText("Set " + date.toString("MM/dd hh:mm"));
291 } 290 }
292 291
293 ////////////////////////////////////////////////////////////////////////////// 292 //////////////////////////////////////////////////////////////////////////////
294 293
295 void OSTC3Operations::setName(const QString &newName) 294 void OSTC3Operations::setName(const QString &newName)
299 char buffer[60]; 298 char buffer[60];
300 memset(buffer, 0, sizeof buffer); 299 memset(buffer, 0, sizeof buffer);
301 strncpy(buffer, newName.toLatin1().constData(), sizeof buffer); 300 strncpy(buffer, newName.toLatin1().constData(), sizeof buffer);
302 301
303 unsigned char echo = retryCommand(_serial, 'c'); // 0x63 Send custom text 302 unsigned char echo = retryCommand(_serial, 'c'); // 0x63 Send custom text
304 if( echo != 'c' ) 303 if (echo != 'c')
305 LOG_THROW("Bad text reply (1)"); 304 LOG_THROW("Bad text reply (1)");
306 305
307 _serial.writeBlock((unsigned char*)buffer, sizeof buffer); 306 _serial.writeBlock((unsigned char *) buffer, sizeof buffer);
308 _serial.sleep(5); 307 _serial.sleep(5);
309 308
310 unsigned char ok = _serial.readByte(); 309 unsigned char ok = _serial.readByte();
311 if( ok != 0x4D ) // DOWNLOAD modes only. 310 if (ok != 0x4D) // DOWNLOAD modes only.
312 LOG_THROW("Bad text reply (2)"); 311 LOG_THROW("Bad text reply (2)");
313 312
314 getIdentity(); 313 getIdentity();
315 // Echo the first line of customtext: 314 // Echo the first line of customtext:
316 writeText(newName.left(12).trimmed()); 315 writeText(newName.left(12).trimmed());
329 return QImage(); 328 return QImage();
330 } 329 }
331 330
332 ////////////////////////////////////////////////////////////////////////////// 331 //////////////////////////////////////////////////////////////////////////////
333 332
334 static unsigned char ostc3SecretKey[16] = { 333 static unsigned char ostc3SecretKey[16]
335 241,233, 176, 48, 334 = {241, 233, 176, 48, 69, 111, 190, 85, 255, 231, 248, 49, 19, 108, 242, 254};
336 69,111, 190, 85,
337 255,231, 248, 49,
338 19,108, 242,254
339 };
340 335
341 ////////////////////////////////////////////////////////////////////////////// 336 //////////////////////////////////////////////////////////////////////////////
342 337
343 void OSTC3Operations::eraseRange(unsigned int addr, unsigned int size) 338 void OSTC3Operations::eraseRange(unsigned int addr, unsigned int size)
344 { 339 {
350 buffer[0] = UPPER(addr); 345 buffer[0] = UPPER(addr);
351 buffer[1] = HIGH(addr); 346 buffer[1] = HIGH(addr);
352 buffer[2] = LOW(addr); 347 buffer[2] = LOW(addr);
353 buffer[3] = LOW(size); 348 buffer[3] = LOW(size);
354 349
355 unsigned char reply = retryCommand(_serial, 'B'); // Command 'B' 350 unsigned char reply = retryCommand(_serial, 'B'); // Command 'B'
356 if( reply != 0x42 ) 351 if (reply != 0x42)
357 LOG_THROW("eraseRange (1)"); 352 LOG_THROW("eraseRange (1)");
358 353
359 _serial.writeBlock(buffer, 4); 354 _serial.writeBlock(buffer, 4);
360 355
361 // Wait (120/4)ms by block of 4K, plus 3% VAT to be sure. 356 // Wait (120/4)ms by block of 4K, plus 3% VAT to be sure.
362 _serial.sleep(40 + size * 31); 357 _serial.sleep(40 + size * 31);
363 358
364 unsigned char ok = _serial.readByte(); 359 unsigned char ok = _serial.readByte();
365 if( ok != 0x4c ) // SERVICE MODE acknowledge. 360 if (ok != 0x4c) // SERVICE MODE acknowledge.
366 LOG_THROW("eraseRange (2)"); 361 LOG_THROW("eraseRange (2)");
367 } 362 }
368 363
369 ////////////////////////////////////////////////////////////////////////////// 364 //////////////////////////////////////////////////////////////////////////////
370 365
371 void OSTC3Operations::writeBlock(unsigned int addr, 366 void OSTC3Operations::writeBlock(unsigned int addr, const unsigned char *data, unsigned int size)
372 const unsigned char *data,
373 unsigned int size)
374 { 367 {
375 unsigned char buffer[3]; 368 unsigned char buffer[3];
376 buffer[0] = UPPER(addr); 369 buffer[0] = UPPER(addr);
377 buffer[1] = HIGH(addr); 370 buffer[1] = HIGH(addr);
378 buffer[2] = LOW(addr); 371 buffer[2] = LOW(addr);
379 372
380 unsigned char reply = retryCommand(_serial, '0'); // 0x30 373 unsigned char reply = retryCommand(_serial, '0'); // 0x30
381 if( reply != '0' ) 374 if (reply != '0')
382 LOG_THROW("startWrite"); 375 LOG_THROW("startWrite");
383 376
384 _serial.writeBlock(buffer, sizeof buffer); 377 _serial.writeBlock(buffer, sizeof buffer);
385 _serial.sleep(2); 378 _serial.sleep(2);
386 379
389 // 1KB = 240 + 1000 = 1240 : Ok. 382 // 1KB = 240 + 1000 = 1240 : Ok.
390 // 4KB = 1.1sec : Ok. 383 // 4KB = 1.1sec : Ok.
391 _serial.sleep(1100); 384 _serial.sleep(1100);
392 385
393 unsigned char ok = _serial.readByte(); 386 unsigned char ok = _serial.readByte();
394 if( ok != 0x4c && ok != 0x4d ) // DOWNLOAD or SERVICE modes. 387 if (ok != 0x4c && ok != 0x4d) // DOWNLOAD or SERVICE modes.
395 LOG_THROW("stopWrite"); 388 LOG_THROW("stopWrite");
396 } 389 }
397 390
398 391 //////////////////////////////////////////////////////////////////////////////
399 ////////////////////////////////////////////////////////////////////////////// 392
400 393 void OSTC3Operations::readBlock(unsigned int addr, unsigned char *ptr, unsigned int size)
401 void OSTC3Operations::readBlock(unsigned int addr, unsigned char* ptr, unsigned int size)
402 { 394 {
403 unsigned char buffer[6]; 395 unsigned char buffer[6];
404 buffer[0] = UPPER(addr); 396 buffer[0] = UPPER(addr);
405 buffer[1] = HIGH(addr); 397 buffer[1] = HIGH(addr);
406 buffer[2] = LOW(addr); 398 buffer[2] = LOW(addr);
407 buffer[3] = UPPER(size); 399 buffer[3] = UPPER(size);
408 buffer[4] = HIGH(size); 400 buffer[4] = HIGH(size);
409 buffer[5] = LOW(size); 401 buffer[5] = LOW(size);
410 402
411 unsigned char reply = retryCommand(_serial, 0x20); // Command ' ' 403 unsigned char reply = retryCommand(_serial, 0x20); // Command ' '
412 if( reply != 0x20 ) 404 if (reply != 0x20)
413 LOG_THROW("readBytes"); 405 LOG_THROW("readBytes");
414 406
415 _serial.writeBlock(buffer, sizeof buffer); 407 _serial.writeBlock(buffer, sizeof buffer);
416 _serial.sleep(500); // Allow some time to start emitting... 408 _serial.sleep(500); // Allow some time to start emitting...
417 _serial.readBlock(ptr, size); 409 _serial.readBlock(ptr, size);
418 410
419 // Note: in that case, the OK byte is send AFTER the data block. 411 // Note: in that case, the OK byte is send AFTER the data block.
420 unsigned char ok = _serial.readByte(); 412 unsigned char ok = _serial.readByte();
421 if( ok != 0x4C ) // SERVICE modes only. 413 if (ok != 0x4C) // SERVICE modes only.
422 LOG_THROW("readBytes (2)"); 414 LOG_THROW("readBytes (2)");
423 } 415 }
424 416
425 ////////////////////////////////////////////////////////////////////////////// 417 //////////////////////////////////////////////////////////////////////////////
426 418
432 buffer[2] = UPPER(checksum); 424 buffer[2] = UPPER(checksum);
433 buffer[3] = UP32(checksum); 425 buffer[3] = UP32(checksum);
434 426
435 // Compute magic checksum's checksum. 427 // Compute magic checksum's checksum.
436 buffer[4] = 0x55; 428 buffer[4] = 0x55;
437 buffer[4] ^= buffer[0]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7); 429 buffer[4] ^= buffer[0];
438 buffer[4] ^= buffer[1]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7); 430 buffer[4] = (buffer[4] << 1 | buffer[4] >> 7);
439 buffer[4] ^= buffer[2]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7); 431 buffer[4] ^= buffer[1];
440 buffer[4] ^= buffer[3]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7); 432 buffer[4] = (buffer[4] << 1 | buffer[4] >> 7);
441 433 buffer[4] ^= buffer[2];
442 unsigned char reply = retryCommand(_serial, 0x50); // 'P' : send FW to bootloader 434 buffer[4] = (buffer[4] << 1 | buffer[4] >> 7);
443 if( reply != 0x50 ) 435 buffer[4] ^= buffer[3];
436 buffer[4] = (buffer[4] << 1 | buffer[4] >> 7);
437
438 unsigned char reply = retryCommand(_serial, 0x50); // 'P' : send FW to bootloader
439 if (reply != 0x50)
444 LOG_THROW("Flashing start (1)"); 440 LOG_THROW("Flashing start (1)");
445 441
446 _serial.writeBlock(buffer, sizeof buffer); 442 _serial.writeBlock(buffer, sizeof buffer);
447 unsigned char ok = _serial.readByte(); 443 unsigned char ok = _serial.readByte();
448 if( ok != 0x4C ) // SERVICE modes only. 444 if (ok != 0x4C) // SERVICE modes only.
449 LOG_THROW("Flashing start (2)"); 445 LOG_THROW("Flashing start (2)");
450 446
451 // NOTE: the device never return, because it always do a reset, 447 // NOTE: the device never return, because it always do a reset,
452 // with ot without reprogramming... 448 // with ot without reprogramming...
453 _serial.sleep(500); 449 _serial.sleep(500);
475 #endif 471 #endif
476 472
477 QRegularExpression OSTC3Operations::portTemplate() const 473 QRegularExpression OSTC3Operations::portTemplate() const
478 { 474 {
479 #if defined(Q_OS_MAC) 475 #if defined(Q_OS_MAC)
480 return QRegularExpression("tty.usbserial-.*", 476 return QRegularExpression("tty.usbserial-.*", QRegularExpression::CaseInsensitiveOption);
481 QRegularExpression::CaseInsensitiveOption);
482 #elif defined(Q_OS_LINUX) 477 #elif defined(Q_OS_LINUX)
483 // Debian, Ubuntu, RedHat, CentOS, SUSE 478 // Debian, Ubuntu, RedHat, CentOS, SUSE
484 return QRegularExpression("ttyUSB.*"); // default: case-sensitive 479 return QRegularExpression("ttyUSB.*"); // default: case-sensitive
485 #elif defined(Q_OS_WIN) 480 #elif defined(Q_OS_WIN)
486 return QRegularExpression("COM.*"); // default: case-sensitive 481 return QRegularExpression("COM.*"); // default: case-sensitive
487 #endif 482 #endif
488 } 483 }
489 ////////////////////////////////////////////////////////////////////////////// 484 //////////////////////////////////////////////////////////////////////////////
490 485
491 void OSTC3Operations::connectServiceMode() 486 void OSTC3Operations::connectServiceMode()
492 { 487 {
493 LOG_TRACE( "Enter service mode..." ); 488 LOG_TRACE("Enter service mode...");
494 489
495 // NOTE: Service mode requires a special starting sequence, different from 490 // NOTE: Service mode requires a special starting sequence, different from
496 // the usual download mode state. 491 // the usual download mode state.
497 // Also, the general acknowledge byte is changed to 0x4c 'L'. 492 // Also, the general acknowledge byte is changed to 0x4c 'L'.
498 493
499 assert( _connectMode != SERVICE_MODE ); 494 assert(_connectMode != SERVICE_MODE);
500 495
501 if( _connectMode == CLOSED_MODE ) 496 if (_connectMode == CLOSED_MODE) {
502 { 497 _serial.open(Settings::port, emulatorName);
503 _serial.open( Settings::port, emulatorName);
504 _serial.sleep(333); // Initial 1/3 sec before trying service mode... 498 _serial.sleep(333); // Initial 1/3 sec before trying service mode...
505 } 499 }
506 for(int retry=0; retry < 10; ++retry) 500 for (int retry = 0; retry < 10; ++retry) {
507 { 501 unsigned char serviceMode[] = {0xAA, 0xAB, 0xCD, 0xEF};
508 unsigned char serviceMode[] = { 0xAA, 0xAB, 0xCD, 0xEF };
509 502
510 try { 503 try {
511 _serial.writeBlock(serviceMode, sizeof serviceMode); 504 _serial.writeBlock(serviceMode, sizeof serviceMode);
512 } 505 } catch (const WriteTimeout &) {
513 catch(const WriteTimeout&) {
514 // Bluetooth not present: one can open the pseudo COM port, 506 // Bluetooth not present: one can open the pseudo COM port,
515 // but we will have a timeout on first write byte... 507 // but we will have a timeout on first write byte...
516 if( retry < 9 ) { 508 if (retry < 9) {
517 LOG_INFO("Cannot connect to " << Settings::port <<" (" << (retry+1) << "/10)..."); 509 LOG_INFO("Cannot connect to " << Settings::port << " (" << (retry + 1) << "/10)...");
518 _serial.sleep(1000); 510 _serial.sleep(1000);
519 continue; 511 continue;
520 } 512 }
521 LOG_THROW("Cannot connect to " << model() << "."); 513 LOG_THROW("Cannot connect to " << model() << ".");
522 return; 514 return;
527 519
528 //---- Check acknowledge: 520 //---- Check acknowledge:
529 unsigned char echo = 0; 521 unsigned char echo = 0;
530 try { 522 try {
531 echo = _serial.readByte(); 523 echo = _serial.readByte();
524 } catch (...) {
532 } 525 }
533 catch(...) {} 526
534 527 if (echo != 0x4b) {
535 if( echo != 0x4b ) { 528 serviceModeFailed:
536 serviceModeFailed: 529 if (retry < 9) {
537 if( retry < 9 )
538 {
539 _serial.purge(); 530 _serial.purge();
540 _serial.sleep(400); 531 _serial.sleep(400);
541 continue; 532 continue;
542 } 533 }
543 LOG_THROW("Unable to enter " << model() <<" service mode"); 534 LOG_THROW("Unable to enter " << model() << " service mode");
544 } 535 }
545 536
546 echo = _serial.readByte(); 537 echo = _serial.readByte();
547 if( echo != 0xAB ) 538 if (echo != 0xAB)
548 goto serviceModeFailed; 539 goto serviceModeFailed;
549 echo = _serial.readByte(); 540 echo = _serial.readByte();
550 if( echo != 0xCD ) 541 if (echo != 0xCD)
551 goto serviceModeFailed; 542 goto serviceModeFailed;
552 echo = _serial.readByte(); 543 echo = _serial.readByte();
553 if( echo != 0xEF ) 544 if (echo != 0xEF)
554 goto serviceModeFailed; 545 goto serviceModeFailed;
555 echo = _serial.readByte(); 546 echo = _serial.readByte();
556 if( echo != 0x4c ) // SERVICE modes only. 547 if (echo != 0x4c) // SERVICE modes only.
557 goto serviceModeFailed; 548 goto serviceModeFailed;
558 break; 549 break;
559 } 550 }
560 _connectMode = SERVICE_MODE; 551 _connectMode = SERVICE_MODE;
561 } 552 }
581 572
582 //---- Upload Firmware --------------------------------------------------- 573 //---- Upload Firmware ---------------------------------------------------
583 LOG_INFO("Uploading firmware."); 574 LOG_INFO("Uploading firmware.");
584 writeText(" Uploading..."); 575 writeText(" Uploading...");
585 576
586 for(int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK) 577 for (int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK) {
587 {
588 unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f); 578 unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f);
589 writeText( QString(" Uploading %1%") 579 writeText(QString(" Uploading %1%").arg(percent, 2));
590 .arg(percent, 2) );
591 PROGRESS(percent, 100); 580 PROGRESS(percent, 100);
592 581
593 writeBlock(FIRMWARE_AREA+len, hex.data()+len, FIRMWARE_BLOCK); 582 writeBlock(FIRMWARE_AREA + len, hex.data() + len, FIRMWARE_BLOCK);
594 } 583 }
595 PROGRESS(100, 100); 584 PROGRESS(100, 100);
596 585
597 //---- Verify firmware --------------------------------------------------- 586 //---- Verify firmware ---------------------------------------------------
598 LOG_INFO("Verify firmware."); 587 LOG_INFO("Verify firmware.");
599 writeText(" Verifying..."); 588 writeText(" Verifying...");
600 { 589 {
601 unsigned char* buffer = new unsigned char[FIRMWARE_SIZE]; 590 unsigned char *buffer = new unsigned char[FIRMWARE_SIZE];
602 Q_CHECK_PTR(buffer); 591 Q_CHECK_PTR(buffer);
603 592
604 for(int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK) 593 for (int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK) {
605 {
606 unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f); 594 unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f);
607 writeText( QString(" Verifying %1%") 595 writeText(QString(" Verifying %1%").arg(percent, 2));
608 .arg(percent, 2) );
609 PROGRESS(percent, 100); 596 PROGRESS(percent, 100);
610 597
611 readBlock(FIRMWARE_AREA+len, buffer+len, FIRMWARE_BLOCK); 598 readBlock(FIRMWARE_AREA + len, buffer + len, FIRMWARE_BLOCK);
612 } 599 }
613 PROGRESS(100, 100); 600 PROGRESS(100, 100);
614 qApp->processEvents(QEventLoop::ExcludeUserInputEvents, 10); 601 qApp->processEvents(QEventLoop::ExcludeUserInputEvents, 10);
615 602
616 for(int i=0; i<FIRMWARE_SIZE; ++i) 603 for (int i = 0; i < FIRMWARE_SIZE; ++i)
617 if( buffer[i] != hex.data()[i] ) 604 if (buffer[i] != hex.data()[i]) {
618 {
619 writeText(" Verify FAILED"); 605 writeText(" Verify FAILED");
620 LOG_THROW("readback is different"); 606 LOG_THROW("readback is different");
621 } 607 }
622 608
623 delete[] buffer; 609 delete[] buffer;
625 PROGRESS_THROTTLE(); 611 PROGRESS_THROTTLE();
626 612
627 //---- Flashing firmware ------------------------------------------------- 613 //---- Flashing firmware -------------------------------------------------
628 LOG_INFO("Programming."); 614 LOG_INFO("Programming.");
629 writeText(" Programming..."); 615 writeText(" Programming...");
630 upgradeFirmware( hex.checksum() ); 616 upgradeFirmware(hex.checksum());
631 617
632 //---- Done -------------------------------------------------------------- 618 //---- Done --------------------------------------------------------------
633 // Low-level close, to avoid trying to send a 0xFF byte... 619 // Low-level close, to avoid trying to send a 0xFF byte...
634 _serial.close(); 620 _serial.close();
635 _connectMode = CLOSED_MODE; 621 _connectMode = CLOSED_MODE;
636 LOG_INFO("Upgrade done."); 622 LOG_INFO("Upgrade done.");
637 PROGRESS_RESET(); 623 PROGRESS_RESET();
638 } 624 }
639 625
640 void OSTC3Operations::loadFirmware(HexFile& hex, const QString& fileName) const 626 void OSTC3Operations::loadFirmware(HexFile &hex, const QString &fileName) const
641 { 627 {
642 hex.allocate(FIRMWARE_SIZE); 628 hex.allocate(FIRMWARE_SIZE);
643 hex.loadEncrypted(fileName, ostc3SecretKey); 629 hex.loadEncrypted(fileName, ostc3SecretKey);
644 } 630 }
645 631
658 ////////////////////////////////////////////////////////////////////////////// 644 //////////////////////////////////////////////////////////////////////////////
659 645
660 HardwareOperations::CompanionFeatures OSTC3Operations::supported() const 646 HardwareOperations::CompanionFeatures OSTC3Operations::supported() const
661 { 647 {
662 // No ICON, no DUMPSCREEN, no VPM 648 // No ICON, no DUMPSCREEN, no VPM
663 return CompanionFeatures(PARAMETERS|DATE|NAME|FIRMWARE 649 return CompanionFeatures(PARAMETERS | DATE | NAME | FIRMWARE | HELIUM_DIVE | CCR_DIVE);
664 |HELIUM_DIVE|CCR_DIVE);
665 } 650 }
666 651
667 ////////////////////////////////////////////////////////////////////////////// 652 //////////////////////////////////////////////////////////////////////////////
668 void OSTC3Operations::getSignal() 653 void OSTC3Operations::getSignal()
669 { 654 {
670 return; 655 return;
671 } 656 }
672 void OSTC3Operations::getAllHeader(unsigned char* pBuffer) 657 void OSTC3Operations::getAllHeader(unsigned char *pBuffer)
673 { 658 {
674 return; 659 return;
675 } 660 }
676 void OSTC3Operations::writeAllHeader(unsigned char* pBuffer) 661 void OSTC3Operations::writeAllHeader(unsigned char *pBuffer)
677 { 662 {
678 return; 663 return;
679 } 664 }
680 665
681 void OSTC3Operations::getAllSamples(unsigned char* pBuffer) 666 void OSTC3Operations::getAllSamples(unsigned char *pBuffer)
682 { 667 {
683 return; 668 return;
684 } 669 }
685 void OSTC3Operations::writeAllSamples(unsigned char* pBuffer) 670 void OSTC3Operations::writeAllSamples(unsigned char *pBuffer)
686 { 671 {
687 return; 672 return;
688 } 673 }