1 #include "firmwareuploaderwindow.h"
2 #include "ui_firmwareuploaderwindow.h"
3 #include "mainwindow.h"
4
5 #include <QFile>
6
7 //You might wonder: Collin, what in the hell is this for? Firmware uploader? For what? I'm interested! Well, it's a custom
8 //firmware uploader for a motor controller I built. Why would that be in this project. Cuz. It's not really relevant
9 //to anyone else but might serve as a decent reference for a few things: How to make an uploader interface that runs over CAN,
10 //how to lay out a screen like this, how to make a comm protocol for firmware updating over CAN. But, most things use UDS
11 //for firmware updates and wouldn't need this specific code. But, it might be able to be turned into a UDS firmware uploader or downloader.
12 //Note that this screen is specifically hidden by default because of it's oddball status. You have to re-enable it in mainwindow.cpp to see it.
13
FirmwareUploaderWindow(const QVector<CANFrame> * frames,QWidget * parent)14 FirmwareUploaderWindow::FirmwareUploaderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
15 QDialog(parent),
16 ui(new Ui::FirmwareUploaderWindow)
17 {
18 ui->setupUi(this);
19 setWindowFlags(Qt::Window);
20
21 transferInProgress = false;
22 startedProcess = false;
23 firmwareSize = 0;
24 currentSendingPosition = 0;
25 baseAddress = 0;
26 bus = 0;
27 modelFrames = frames;
28
29 ui->lblFilename->setText("");
30 ui->spinBus->setValue(0);
31 ui->spinBus->setMaximum(1);
32 ui->txtBaseAddr->setText("0x100");
33 updateProgress();
34
35 timer = new QTimer();
36 timer->setInterval(100); //100ms without a reply will cause us to attempt a resend
37
38 connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
39 connect(ui->btnLoadFile, SIGNAL(clicked(bool)), this, SLOT(handleLoadFile()));
40 connect(ui->btnStartStop, SIGNAL(clicked(bool)), this, SLOT(handleStartStopTransfer()));
41 connect(timer, SIGNAL(timeout()), this, SLOT(timerElapsed()));
42 }
43
~FirmwareUploaderWindow()44 FirmwareUploaderWindow::~FirmwareUploaderWindow()
45 {
46 timer->stop();
47 CANConManager::getInstance()->removeAllTargettedFrames(this);
48 delete timer;
49 delete ui;
50 }
51
updateProgress()52 void FirmwareUploaderWindow::updateProgress()
53 {
54 ui->lblProgress->setText(QString::number(currentSendingPosition * 4) + " of " + QString::number(firmwareSize) + " transferred");
55 }
56
updatedFrames(int numFrames)57 void FirmwareUploaderWindow::updatedFrames(int numFrames)
58 {
59 //CANFrame thisFrame;
60 if (numFrames == -1) //all frames deleted.
61 {
62 }
63 else if (numFrames == -2) //all new set of frames.
64 {
65 }
66 else //just got some new frames. See if they are relevant.
67 {
68 /*
69 //run through the supposedly new frames in order
70 for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
71 {
72 thisFrame = modelFrames->at(i);
73 }
74 */
75 }
76 }
77
gotTargettedFrame(CANFrame frame)78 void FirmwareUploaderWindow::gotTargettedFrame(CANFrame frame)
79 {
80 const unsigned char *data = reinterpret_cast<const unsigned char *>(frame.payload().constData());
81 int dataLen = frame.payload().count();
82
83 qDebug() << "FUW: Got targetted frame with id " << frame.frameId();
84 if (frame.frameId() == (uint32_t)(baseAddress + 0x10) && (dataLen == 8) ) {
85 qDebug() << "Start firmware reply";
86 if ((data[0] == 0xAD) && (data[1] == 0xDE))
87 {
88 if ((data[2] == 0xAF) && (data[3] == 0xDE))
89 {
90 qDebug() << "There's dead beef here";
91 if ( (data[4] == (token & 0xFF)) && (data[5] == ((token >> 8) & 0xFF) ) )
92 {
93 if ((data[6] == ((token >> 16) & 0xFF)) && (data[7] == ((token >> 24) & 0xFF)))
94 {
95 qDebug() << "starting firmware process";
96 //MainWindow::getReference()->setTargettedID(baseAddress + 0x20);
97 transferInProgress = true;
98 sendFirmwareChunk();
99 }
100 }
101 }
102 }
103 }
104
105 if (frame.frameId() == (uint32_t)(baseAddress + 0x20)) {
106 qDebug() << "Firmware reception success reply";
107 int seq = data[0] + (256 * data[1]);
108 if (seq == currentSendingPosition)
109 {
110 currentSendingPosition++;
111 if (currentSendingPosition * 4 > firmwareSize || currentSendingPosition > 65535)
112 {
113 transferInProgress = false;
114 timer->stop();
115 handleStartStopTransfer();
116 ui->progressBar->setValue(100);
117 sendFirmwareEnding();
118 }
119 else
120 {
121 ui->progressBar->setValue((400 * currentSendingPosition) / firmwareSize);
122 updateProgress();
123 sendFirmwareChunk();
124 }
125 }
126 }
127 }
128
timerElapsed()129 void FirmwareUploaderWindow::timerElapsed()
130 {
131 sendFirmwareChunk(); //resend
132 }
133
sendFirmwareChunk()134 void FirmwareUploaderWindow::sendFirmwareChunk()
135 {
136 CANFrame *output = new CANFrame;
137 int firmwareLocation = currentSendingPosition * 4;
138 int xorByte = 0;
139 output->setExtendedFrameFormat(false);
140 QByteArray bytes(7,0);
141 output->bus = bus;
142 output->setFrameId(baseAddress + 0x16);
143 output->payload()[0] = currentSendingPosition & 0xFF;
144 output->payload()[1] = (currentSendingPosition >> 8) & 0xFF;
145 output->payload()[2] = firmwareData[firmwareLocation++];
146 output->payload()[3] = firmwareData[firmwareLocation++];
147 output->payload()[4] = firmwareData[firmwareLocation++];
148 output->payload()[5] = firmwareData[firmwareLocation++];
149 for (int i = 0; i < 6; i++) xorByte = xorByte ^ static_cast<unsigned char>(output->payload()[i]);
150 output->payload()[6] = xorByte;
151 output->setPayload(bytes);
152 CANConManager::getInstance()->sendFrame(*output);
153 timer->start();
154 }
155
sendFirmwareEnding()156 void FirmwareUploaderWindow::sendFirmwareEnding()
157 {
158 CANFrame *output = new CANFrame;
159 output->setExtendedFrameFormat(false);
160 output->bus = bus;
161 QByteArray bytes(4,0);
162 output->setFrameId(baseAddress + 0x30);
163 output->payload()[3] = 0xC0;
164 output->payload()[2] = 0xDE;
165 output->payload()[1] = 0xFA;
166 output->payload()[0] = 0xDE;
167 output->setPayload(bytes);
168 //sendCANFrame(output, bus);
169 }
170
handleStartStopTransfer()171 void FirmwareUploaderWindow::handleStartStopTransfer()
172 {
173 startedProcess = !startedProcess;
174
175 if (startedProcess) //start the process
176 {
177 ui->progressBar->setValue(0);
178 ui->btnStartStop->setText("Stop Upload");
179 token = Utility::ParseStringToNum(ui->txtToken->text());
180 bus = ui->spinBus->value();
181 baseAddress = Utility::ParseStringToNum(ui->txtBaseAddr->text());
182 qDebug() << "Base address: " + QString::number(baseAddress);
183 CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
184 CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
185 CANFrame *output = new CANFrame;
186 output->setExtendedFrameFormat(false);
187 QByteArray bytes(8,0);
188 output->bus = bus;
189 output->setFrameId(baseAddress);
190 output->setFrameType(QCanBusFrame::DataFrame);
191
192 bytes[0] = 0xEF;
193 bytes[1] = 0xBE;
194 bytes[2] = 0xAD;
195 bytes[3] = 0xDE;
196 bytes[4] = token & 0xFF;
197 bytes[5] = (token >> 8) & 0xFF;
198 bytes[6] = (token >> 16) & 0xFF;
199 bytes[7] = (token >> 24) & 0xFF;
200 output->setPayload(bytes);
201 CANConManager::getInstance()->sendFrame(*output);
202 }
203 else //stop anything in process
204 {
205 ui->btnStartStop->setText("Start Upload");
206 CANConManager::getInstance()->removeAllTargettedFrames(this);
207 }
208 }
209
handleLoadFile()210 void FirmwareUploaderWindow::handleLoadFile()
211 {
212 QString filename;
213 QFileDialog dialog;
214
215 QStringList filters;
216 filters.append(QString(tr("Raw firmware binary (*.bin)")));
217
218 dialog.setFileMode(QFileDialog::ExistingFile);
219 dialog.setNameFilters(filters);
220 dialog.setViewMode(QFileDialog::Detail);
221
222 if (dialog.exec() == QDialog::Accepted)
223 {
224 filename = dialog.selectedFiles()[0];
225
226 loadBinaryFile(filename);
227 }
228 }
229
loadBinaryFile(QString filename)230 void FirmwareUploaderWindow::loadBinaryFile(QString filename)
231 {
232
233 if (transferInProgress) handleStartStopTransfer();
234
235 QFile *inFile = new QFile(filename);
236
237 if (!inFile->open(QIODevice::ReadOnly))
238 {
239 delete inFile;
240 return;
241 }
242
243 firmwareData = inFile->readAll();
244
245 currentSendingPosition = 0;
246 firmwareSize = firmwareData.length();
247
248 updateProgress();
249
250 inFile->close();
251 delete inFile;
252 }
253
254