├── README.md
├── images
├── new.png
├── save.png
├── undo.png
├── clear.png
├── connect.png
├── print.png
├── la-8chan.png
├── settings.png
├── disconnect.png
└── application-exit.png
├── dockwidgets.qrc
├── terminal.qrc
├── loader-intelhex.h
├── .gitignore
├── load-ice40.h
├── load-image.h
├── dockwidgets.pro
├── main.cpp
├── console.h
├── programthread.h
├── loader-ds30loader.h
├── loader-intelhex.cpp
├── settingsdialog.h
├── console.cpp
├── settingsdialog.ui
├── load-ice40.cpp
├── load-image.cpp
├── mainwindow.h
├── settingsdialog.cpp
├── loader-ds30loader.cpp
├── programthread.cpp
├── LICENSE
└── intelhexclass.cpp
/README.md:
--------------------------------------------------------------------------------
1 | # BusTerminal
2 | Very basic serial terminal with logic analyzer graph. Qt5-based.
3 |
--------------------------------------------------------------------------------
/images/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/new.png
--------------------------------------------------------------------------------
/images/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/save.png
--------------------------------------------------------------------------------
/images/undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/undo.png
--------------------------------------------------------------------------------
/images/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/clear.png
--------------------------------------------------------------------------------
/images/connect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/connect.png
--------------------------------------------------------------------------------
/images/print.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/print.png
--------------------------------------------------------------------------------
/images/la-8chan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/la-8chan.png
--------------------------------------------------------------------------------
/images/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/settings.png
--------------------------------------------------------------------------------
/images/disconnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/disconnect.png
--------------------------------------------------------------------------------
/images/application-exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DangerousPrototypes/BusTerminal/HEAD/images/application-exit.png
--------------------------------------------------------------------------------
/dockwidgets.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/new.png
4 | images/print.png
5 | images/save.png
6 | images/undo.png
7 | images/la-8chan.png
8 |
9 |
10 |
--------------------------------------------------------------------------------
/terminal.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/connect.png
4 | images/disconnect.png
5 | images/application-exit.png
6 | images/settings.png
7 | images/clear.png
8 |
9 |
10 |
--------------------------------------------------------------------------------
/loader-intelhex.h:
--------------------------------------------------------------------------------
1 | #ifndef LOADERINTELHEX_H
2 | #define LOADERINTELHEX_H
3 |
4 | #include
5 |
6 | class loadhexworker: public QObject
7 | {
8 | Q_OBJECT
9 |
10 | public:
11 | loadhexworker(const QString &fileName);
12 | ~loadhexworker();
13 |
14 | public slots:
15 | void load();
16 |
17 | signals:
18 | void info(const QString &info);
19 | void error(const QString &error);
20 | void output(const QByteArray &firmware);
21 | void finished();
22 |
23 | private:
24 | QString m_filename;
25 |
26 |
27 | };
28 |
29 | #endif // LOADERINTELHEX_H
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 | *.slo
3 | *.lo
4 | *.o
5 | *.a
6 | *.la
7 | *.lai
8 | *.so
9 | *.dll
10 | *.dylib
11 |
12 | # Qt-es
13 | object_script.*.Release
14 | object_script.*.Debug
15 | *_plugin_import.cpp
16 | /.qmake.cache
17 | /.qmake.stash
18 | *.pro.user
19 | *.pro.user.*
20 | *.qbs.user
21 | *.qbs.user.*
22 | *.moc
23 | moc_*.cpp
24 | moc_*.h
25 | qrc_*.cpp
26 | ui_*.h
27 | *.qmlc
28 | *.jsc
29 | Makefile*
30 | *build-*
31 |
32 | # Qt unit tests
33 | target_wrapper.*
34 |
35 | # QtCreator
36 | *.autosave
37 |
38 | # QtCreator Qml
39 | *.qmlproject.user
40 | *.qmlproject.user.*
41 |
42 | # QtCreator CMake
43 | CMakeLists.txt.user*
44 |
45 | build/*
46 | *.dll
47 |
48 |
--------------------------------------------------------------------------------
/load-ice40.h:
--------------------------------------------------------------------------------
1 | #ifndef LOADICE40_H
2 | #define LOADICE40_H
3 |
4 | #include
5 | #include
6 |
7 | class loadIce40: public QObject
8 | {
9 | Q_OBJECT
10 |
11 | public:
12 | explicit loadIce40(const QString &portName, const QString &fileName);
13 | ~loadIce40();
14 |
15 | public slots:
16 | void load();
17 |
18 | signals:
19 | void response(const QString &s);
20 | void error(const QString &s);
21 | void timeout(const QString &s);
22 | void info(const QString &s);
23 | void progress(const quint8 &c);
24 | void finished();
25 |
26 | private:
27 | quint8 makeCrc(QByteArray buf);
28 | QByteArray sendCommandAndWaitForResponse(QByteArray currentRequest, quint16 delay);
29 | qint32 sendFirmware(QByteArray firmware);
30 |
31 | QString m_portName;
32 | QString m_filename;
33 | QSerialPort *m_serial = nullptr;
34 |
35 |
36 | };
37 |
38 | #endif // LOADICE40_H
39 |
--------------------------------------------------------------------------------
/load-image.h:
--------------------------------------------------------------------------------
1 | #ifndef LOADIMAGE_H
2 | #define LOADIMAGE_H
3 |
4 | #include
5 | #include
6 |
7 | class loadImageWorker: public QObject
8 | {
9 | Q_OBJECT
10 |
11 | public:
12 | explicit loadImageWorker(const QString &portName, const QString &fileName);
13 | ~loadImageWorker();
14 |
15 | public slots:
16 | void load();
17 |
18 | signals:
19 | void response(const QString &s);
20 | void error(const QString &s);
21 | void timeout(const QString &s);
22 | void info(const QString &s);
23 | void progress(const quint8 &c);
24 | void finished();
25 |
26 | private:
27 | quint8 makeCrc(QByteArray buf);
28 | QByteArray sendCommandAndWaitForResponse(QByteArray currentRequest, quint16 delay);
29 | qint32 sendFirmware(QByteArray firmware);
30 |
31 | QString m_portName;
32 | QString m_filename;
33 | QSerialPort *m_serial = nullptr;
34 |
35 |
36 | };
37 |
38 | #endif // LOADICE40_H
39 |
--------------------------------------------------------------------------------
/dockwidgets.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2013-07-25T20:43:22
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui serialport concurrent
8 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
9 |
10 | requires(qtConfig(listwidget))
11 | requires(qtConfig(combobox))
12 |
13 | #include(../src/libQDeviceWatcher.pri)
14 |
15 | TARGET = la-tests
16 | TEMPLATE = app
17 |
18 | # Tell the qcustomplot header that it will be used as library:
19 | DEFINES += QCUSTOMPLOT_USE_LIBRARY
20 |
21 | # Link with debug version of qcustomplot if compiling in debug mode, else with release library:
22 | CONFIG(debug, release|debug) {
23 | win32:QCPLIB = qcustomplotd2
24 | else: QCPLIB = qcustomplotd
25 | } else {
26 | win32:QCPLIB = qcustomplot2
27 | else: QCPLIB = qcustomplot
28 | }
29 |
30 | CONFIG(debug, release|debug) {
31 | win32:QDWLIB = QDeviceWatcherd2
32 | else: QDWLIB = QDeviceWatcherd2
33 | } else {
34 | win32:QDWLIB = QDeviceWatcher2
35 | else: QDWLIB = QDeviceWatcher2
36 | }
37 | LIBS += -L./ -l../$$QCPLIB
38 |
39 | #LIBS += -L./ -l../$$QDWLIB
40 |
41 | SOURCES += main.cpp\
42 | intelhexclass.cpp \
43 | load-ice40.cpp \
44 | load-image.cpp \
45 | loader-ds30loader.cpp \
46 | loader-intelhex.cpp \
47 | mainwindow.cpp\
48 | console.cpp
49 |
50 | HEADERS += mainwindow.h\
51 | intelhexclass.h \
52 | console.h \
53 | load-ice40.h \
54 | load-image.h \
55 | loader-ds30loader.h \
56 | loader-intelhex.h
57 |
58 | RESOURCES += dockwidgets.qrc\
59 | terminal.qrc
60 |
61 | FORMS +=
62 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2016 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #include
52 |
53 | #include "mainwindow.h"
54 |
55 | int main(int argc, char *argv[])
56 | {
57 | QApplication app(argc, argv);
58 | Q_INIT_RESOURCE(dockwidgets);
59 | MainWindow mainWin;
60 | mainWin.show();
61 | return app.exec();
62 | }
63 |
--------------------------------------------------------------------------------
/console.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Copyright (C) 2012 Laszlo Papp
5 | ** Contact: https://www.qt.io/licensing/
6 | **
7 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
8 | **
9 | ** $QT_BEGIN_LICENSE:BSD$
10 | ** Commercial License Usage
11 | ** Licensees holding valid commercial Qt licenses may use this file in
12 | ** accordance with the commercial license agreement provided with the
13 | ** Software or, alternatively, in accordance with the terms contained in
14 | ** a written agreement between you and The Qt Company. For licensing terms
15 | ** and conditions see https://www.qt.io/terms-conditions. For further
16 | ** information use the contact form at https://www.qt.io/contact-us.
17 | **
18 | ** BSD License Usage
19 | ** Alternatively, you may use this file under the terms of the BSD license
20 | ** as follows:
21 | **
22 | ** "Redistribution and use in source and binary forms, with or without
23 | ** modification, are permitted provided that the following conditions are
24 | ** met:
25 | ** * Redistributions of source code must retain the above copyright
26 | ** notice, this list of conditions and the following disclaimer.
27 | ** * Redistributions in binary form must reproduce the above copyright
28 | ** notice, this list of conditions and the following disclaimer in
29 | ** the documentation and/or other materials provided with the
30 | ** distribution.
31 | ** * Neither the name of The Qt Company Ltd nor the names of its
32 | ** contributors may be used to endorse or promote products derived
33 | ** from this software without specific prior written permission.
34 | **
35 | **
36 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
47 | **
48 | ** $QT_END_LICENSE$
49 | **
50 | ****************************************************************************/
51 |
52 | #ifndef CONSOLE_H
53 | #define CONSOLE_H
54 |
55 | #include
56 |
57 | class Console : public QPlainTextEdit
58 | {
59 | Q_OBJECT
60 |
61 | signals:
62 | void getData(const QByteArray &data);
63 |
64 | public:
65 | explicit Console(QWidget *parent = nullptr);
66 |
67 | void putData(const QByteArray &data);
68 | void setLocalEchoEnabled(bool set);
69 | void disconnected();
70 | void connected();
71 |
72 | protected:
73 | void keyPressEvent(QKeyEvent *e) override;
74 | void mousePressEvent(QMouseEvent *e) override;
75 | void mouseDoubleClickEvent(QMouseEvent *e) override;
76 | void contextMenuEvent(QContextMenuEvent *e) override;
77 |
78 | private:
79 | bool m_localEchoEnabled = false;
80 | };
81 |
82 | #endif // CONSOLE_H
83 |
--------------------------------------------------------------------------------
/programthread.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 | #ifndef PROGRAMTHREAD_H
51 | #define PROGRAMTHREAD_H
52 | #include
53 | #include
54 | #include
55 | #include
56 |
57 | class programthread : public QThread
58 | {
59 | Q_OBJECT
60 |
61 | public:
62 | explicit programthread(QObject *parent = nullptr);
63 | ~programthread();
64 |
65 | void transaction(const QString &portName, QByteArray &firmware);
66 |
67 | signals:
68 | void response(const QString &s);
69 | void error(const QString &s);
70 | void timeout(const QString &s);
71 | void info(const QString &s);
72 | void progress(const quint8 &c);
73 |
74 | private:
75 | void run() override;
76 | quint8 makeCrc(QByteArray buf);
77 | QByteArray sendCommandAndWaitForResponse(QByteArray currentRequest);
78 | qint32 sendFirmware(QByteArray firmware);
79 |
80 | QString m_portName;
81 | QString m_request;
82 | QByteArray m_firmware;
83 | int m_waitTimeout = 0;
84 | QMutex m_mutex;
85 | QWaitCondition m_cond;
86 | bool m_quit = false;
87 | QSerialPort *m_serial = nullptr;
88 | };
89 | #endif // PROGRAMTHREAD_H
90 |
--------------------------------------------------------------------------------
/loader-ds30loader.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 | #ifndef LOADER_DS30LOADER_H
51 | #define LOADER_DS30LOADER_H
52 |
53 | #include
54 |
55 | class loaderds30loader : public QObject
56 | {
57 | Q_OBJECT
58 |
59 | public:
60 | explicit loaderds30loader(const QString &portName, const QByteArray &firmware);
61 | ~loaderds30loader();
62 |
63 | //void transaction(const QString &portName, QByteArray &firmware);
64 | void setFirmware(QByteArray firmware);
65 | void setSerialPortName(QString portName);
66 | public slots:
67 | void load();
68 |
69 | signals:
70 | void response(const QString &s);
71 | void error(const QString &s);
72 | void timeout(const QString &s);
73 | void info(const QString &s);
74 | void progress(const quint8 &c);
75 | void finished();
76 |
77 | private:
78 | quint8 makeCrc(QByteArray buf);
79 | QByteArray sendCommandAndWaitForResponse(QByteArray currentRequest);
80 | qint32 sendFirmware(QByteArray firmware);
81 |
82 | QString m_portName;
83 | QString m_request;
84 | QByteArray m_firmware;
85 | int m_waitTimeout = 0;
86 | QMutex m_mutex;
87 | QWaitCondition m_cond;
88 | bool m_quit = false;
89 | QSerialPort *m_serial = nullptr;
90 | };
91 | #endif // LOADER_DS30LOADER_H
92 |
--------------------------------------------------------------------------------
/loader-intelhex.cpp:
--------------------------------------------------------------------------------
1 | #include "loader-intelhex.h"
2 | #include
3 | //imported from qtIntegrity, dont know which we really need
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | // !
13 | #include "intelhexclass.h"
14 |
15 | loadhexworker::loadhexworker(const QString &fileName)
16 | {
17 | m_filename=fileName;
18 | }
19 |
20 | loadhexworker::~loadhexworker()
21 | {
22 | }
23 |
24 | void loadhexworker::load()
25 | {
26 | qDebug() <<"Worker::loadhexworker called from: " << QThread::currentThreadId();
27 |
28 | intelhex ihFile;
29 | std::ifstream intelHexInput;
30 | QTime t;
31 | int elapsedTime;
32 |
33 | intelHexInput.open(m_filename.toLatin1(), ifstream::in);
34 |
35 | if(!intelHexInput.good())
36 | {
37 | QString outputError=tr("Flash firmware error. Cannot read file %1.").arg(m_filename);
38 | emit error(outputError);
39 |
40 | }else{
41 |
42 | t.start();
43 |
44 | intelHexInput >> ihFile;
45 |
46 | elapsedTime = t.elapsed();
47 |
48 | if (ihFile.getNoWarnings() < 1 && ihFile.getNoErrors() < 1)
49 | {
50 | QString outputMessage;
51 |
52 | outputMessage += tr("No issues found in file %1.") .arg(m_filename);
53 | outputMessage += tr("\nDecode took %1ms.\n") .arg(elapsedTime);
54 |
55 | QDateTime dateTime = QDateTime::currentDateTime();
56 | QString dateTimeString = dateTime.toString();
57 | outputMessage += tr("Date and time: ") + dateTimeString + "\n";
58 |
59 | emit info(outputMessage);
60 |
61 | QByteArray firmware;
62 | unsigned char f=0xff;
63 |
64 | //I think there is a stream operator to get the HEX out but I don't understand how to use it yet... lame
65 | ihFile.begin();
66 | while(ihFile.endOfData()==false){
67 | ihFile.getData(&f);
68 | firmware.append((char)f);
69 | ++ihFile;
70 | }
71 |
72 | emit output(firmware);
73 | }
74 | else
75 | {
76 | QString outputMessage;
77 |
78 | //statusBar()->showMessage(tr("Issues found in file"));
79 | outputMessage = tr("File %1 contains the following issues:\n").arg(m_filename);
80 |
81 | if (ihFile.getNoWarnings() > 0)
82 | {
83 | outputMessage += "\n";
84 |
85 | while(ihFile.getNoWarnings() > 0)
86 | {
87 | QString qmessage;
88 | string message;
89 |
90 | ihFile.popNextWarning(message);
91 |
92 | qmessage = QString::fromStdString(message);
93 |
94 | outputMessage += tr("WARNING: ");
95 | outputMessage += qmessage;
96 | outputMessage += "\n";
97 | }
98 | }
99 | if (ihFile.getNoErrors() > 0)
100 | {
101 | outputMessage += "\n";
102 |
103 | while (ihFile.getNoErrors() > 0)
104 | {
105 | QString qmessage;
106 | string message;
107 |
108 | ihFile.popNextError(message);
109 |
110 | qmessage = QString::fromStdString(message);
111 |
112 | outputMessage += tr("ERROR: ") + qmessage + "\n";
113 | }
114 | }
115 |
116 | outputMessage += tr("\nDecode took %1ms.\n") .arg(elapsedTime);
117 |
118 | QDateTime dateTime = QDateTime::currentDateTime();
119 | QString dateTimeString = dateTime.toString();
120 | outputMessage += tr("Date and time: ") + dateTimeString + "\n";
121 |
122 | emit info(outputMessage);
123 | }
124 | }
125 |
126 | emit finished();
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/settingsdialog.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Copyright (C) 2012 Laszlo Papp
5 | ** Contact: https://www.qt.io/licensing/
6 | **
7 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
8 | **
9 | ** $QT_BEGIN_LICENSE:BSD$
10 | ** Commercial License Usage
11 | ** Licensees holding valid commercial Qt licenses may use this file in
12 | ** accordance with the commercial license agreement provided with the
13 | ** Software or, alternatively, in accordance with the terms contained in
14 | ** a written agreement between you and The Qt Company. For licensing terms
15 | ** and conditions see https://www.qt.io/terms-conditions. For further
16 | ** information use the contact form at https://www.qt.io/contact-us.
17 | **
18 | ** BSD License Usage
19 | ** Alternatively, you may use this file under the terms of the BSD license
20 | ** as follows:
21 | **
22 | ** "Redistribution and use in source and binary forms, with or without
23 | ** modification, are permitted provided that the following conditions are
24 | ** met:
25 | ** * Redistributions of source code must retain the above copyright
26 | ** notice, this list of conditions and the following disclaimer.
27 | ** * Redistributions in binary form must reproduce the above copyright
28 | ** notice, this list of conditions and the following disclaimer in
29 | ** the documentation and/or other materials provided with the
30 | ** distribution.
31 | ** * Neither the name of The Qt Company Ltd nor the names of its
32 | ** contributors may be used to endorse or promote products derived
33 | ** from this software without specific prior written permission.
34 | **
35 | **
36 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
47 | **
48 | ** $QT_END_LICENSE$
49 | **
50 | ****************************************************************************/
51 |
52 | #ifndef SETTINGSDIALOG_H
53 | #define SETTINGSDIALOG_H
54 |
55 | #include
56 | #include
57 |
58 | QT_BEGIN_NAMESPACE
59 |
60 | namespace Ui {
61 | class SettingsDialog;
62 | }
63 |
64 | class QIntValidator;
65 |
66 | QT_END_NAMESPACE
67 |
68 | class SettingsDialog : public QDialog
69 | {
70 | Q_OBJECT
71 |
72 | public:
73 | struct Settings {
74 | QString name;
75 | qint32 baudRate;
76 | QString stringBaudRate;
77 | QSerialPort::DataBits dataBits;
78 | QString stringDataBits;
79 | QSerialPort::Parity parity;
80 | QString stringParity;
81 | QSerialPort::StopBits stopBits;
82 | QString stringStopBits;
83 | QSerialPort::FlowControl flowControl;
84 | QString stringFlowControl;
85 | bool localEchoEnabled;
86 | };
87 | void fillPortsParameters();
88 | QList fillPortsInfo();
89 | void updateSettings();
90 |
91 | explicit SettingsDialog(QWidget *parent = nullptr);
92 | ~SettingsDialog();
93 |
94 | Settings settings() const;
95 |
96 | private slots:
97 | void showPortInfo(int idx);
98 | void apply();
99 | void checkCustomBaudRatePolicy(int idx);
100 | void checkCustomDevicePathPolicy(int idx);
101 |
102 | //private:
103 |
104 |
105 | private:
106 | Ui::SettingsDialog *m_ui = nullptr;
107 | Settings m_currentSettings;
108 | QIntValidator *m_intValidator = nullptr;
109 | };
110 |
111 | #endif // SETTINGSDIALOG_H
112 |
--------------------------------------------------------------------------------
/console.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Copyright (C) 2012 Laszlo Papp
5 | ** Contact: https://www.qt.io/licensing/
6 | **
7 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
8 | **
9 | ** $QT_BEGIN_LICENSE:BSD$
10 | ** Commercial License Usage
11 | ** Licensees holding valid commercial Qt licenses may use this file in
12 | ** accordance with the commercial license agreement provided with the
13 | ** Software or, alternatively, in accordance with the terms contained in
14 | ** a written agreement between you and The Qt Company. For licensing terms
15 | ** and conditions see https://www.qt.io/terms-conditions. For further
16 | ** information use the contact form at https://www.qt.io/contact-us.
17 | **
18 | ** BSD License Usage
19 | ** Alternatively, you may use this file under the terms of the BSD license
20 | ** as follows:
21 | **
22 | ** "Redistribution and use in source and binary forms, with or without
23 | ** modification, are permitted provided that the following conditions are
24 | ** met:
25 | ** * Redistributions of source code must retain the above copyright
26 | ** notice, this list of conditions and the following disclaimer.
27 | ** * Redistributions in binary form must reproduce the above copyright
28 | ** notice, this list of conditions and the following disclaimer in
29 | ** the documentation and/or other materials provided with the
30 | ** distribution.
31 | ** * Neither the name of The Qt Company Ltd nor the names of its
32 | ** contributors may be used to endorse or promote products derived
33 | ** from this software without specific prior written permission.
34 | **
35 | **
36 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
47 | **
48 | ** $QT_END_LICENSE$
49 | **
50 | ****************************************************************************/
51 |
52 | #include "console.h"
53 |
54 | #include
55 |
56 | Console::Console(QWidget *parent) :
57 | QPlainTextEdit(parent)
58 | {
59 | document()->setMaximumBlockCount(100);
60 | QPalette p = palette();
61 | p.setColor(QPalette::Base, Qt::black);
62 | p.setColor(QPalette::Text, Qt::green);
63 | setPalette(p);
64 | }
65 |
66 | void Console::connected(){
67 | QPalette p = palette();
68 | p.setColor(QPalette::Base, Qt::black);
69 | p.setColor(QPalette::Text, Qt::green);
70 | setPalette(p);
71 | putData("\nConnected\n");
72 | }
73 |
74 | void Console::disconnected(){
75 | QPalette p = palette();
76 | p.setColor(QPalette::Base, Qt::gray);
77 | p.setColor(QPalette::Text, Qt::green);
78 | setPalette(p);
79 | putData("\nDisconnected\n");
80 | }
81 |
82 | void Console::putData(const QByteArray &data)
83 | {
84 | insertPlainText(data);
85 |
86 | QScrollBar *bar = verticalScrollBar();
87 | bar->setValue(bar->maximum());
88 | }
89 |
90 |
91 | void Console::setLocalEchoEnabled(bool set)
92 | {
93 | m_localEchoEnabled = set;
94 | }
95 |
96 | void Console::keyPressEvent(QKeyEvent *e)
97 | {
98 | switch (e->key()) {
99 | case Qt::Key_Backspace:
100 | case Qt::Key_Left:
101 | case Qt::Key_Right:
102 | case Qt::Key_Up:
103 | case Qt::Key_Down:
104 | break;
105 | default:
106 | if (m_localEchoEnabled)
107 | QPlainTextEdit::keyPressEvent(e);
108 | emit getData(e->text().toLocal8Bit());
109 | }
110 | }
111 |
112 | void Console::mousePressEvent(QMouseEvent *e)
113 | {
114 | Q_UNUSED(e)
115 | setFocus();
116 | }
117 |
118 | void Console::mouseDoubleClickEvent(QMouseEvent *e)
119 | {
120 | Q_UNUSED(e)
121 | }
122 |
123 | void Console::contextMenuEvent(QContextMenuEvent *e)
124 | {
125 | Q_UNUSED(e)
126 | }
127 |
--------------------------------------------------------------------------------
/settingsdialog.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SettingsDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 281
10 | 262
11 |
12 |
13 |
14 | Settings
15 |
16 |
17 | -
18 |
19 |
20 | Select Parameters
21 |
22 |
23 |
-
24 |
25 |
26 | BaudRate:
27 |
28 |
29 |
30 | -
31 |
32 |
33 | -
34 |
35 |
36 | Data bits:
37 |
38 |
39 |
40 | -
41 |
42 |
43 | -
44 |
45 |
46 | Parity:
47 |
48 |
49 |
50 | -
51 |
52 |
53 | -
54 |
55 |
56 | Stop bits:
57 |
58 |
59 |
60 | -
61 |
62 |
63 | -
64 |
65 |
66 | Flow control:
67 |
68 |
69 |
70 | -
71 |
72 |
73 |
74 |
75 |
76 | -
77 |
78 |
79 | Select Serial Port
80 |
81 |
82 |
-
83 |
84 |
85 | -
86 |
87 |
88 | Description:
89 |
90 |
91 |
92 | -
93 |
94 |
95 | Manufacturer:
96 |
97 |
98 |
99 | -
100 |
101 |
102 | Serial number:
103 |
104 |
105 |
106 | -
107 |
108 |
109 | Location:
110 |
111 |
112 |
113 | -
114 |
115 |
116 | Vendor ID:
117 |
118 |
119 |
120 | -
121 |
122 |
123 | Product ID:
124 |
125 |
126 |
127 |
128 |
129 |
130 | -
131 |
132 |
-
133 |
134 |
135 | Qt::Horizontal
136 |
137 |
138 |
139 | 96
140 | 20
141 |
142 |
143 |
144 |
145 | -
146 |
147 |
148 | Apply
149 |
150 |
151 |
152 |
153 |
154 | -
155 |
156 |
157 | Additional options
158 |
159 |
160 |
-
161 |
162 |
163 | Local echo
164 |
165 |
166 | true
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/load-ice40.cpp:
--------------------------------------------------------------------------------
1 | #ifndef LOAD_ICE40
2 | #define LOAD_ICE40
3 |
4 | #define BOOTLOADER_HELLO_STR "\xC0"
5 | #define BOOTLOADER_OK 0x4B
6 |
7 | #include
8 | #include
9 |
10 | #include "load-ice40.h"
11 |
12 | loadIce40::loadIce40(const QString &portName, const QString &fileName)
13 | {
14 | m_portName = portName;
15 | m_filename=fileName;
16 | }
17 |
18 | loadIce40::~loadIce40()
19 | {
20 | }
21 |
22 | void loadIce40::load()
23 | {
24 | qDebug() <<"Worker::loadIce40 called from: " << QThread::currentThreadId();
25 |
26 | QFile file(m_filename);
27 | if (!file.open(QIODevice::ReadOnly)) return;
28 | QByteArray blob = file.readAll();
29 | file.close();
30 |
31 | QString outputError=tr("\nBitstream %1 is %2 bytes.\n").arg(m_filename).arg(file.size());
32 | emit info(outputError);
33 |
34 | m_serial = new QSerialPort;
35 |
36 | if (m_portName.isEmpty()) {
37 | emit error(tr("No port name specified"));
38 | return;
39 | }
40 |
41 | m_serial->close();
42 | m_serial->setPortName(m_portName);
43 | m_serial->setBaudRate(921600);//QSerialPort::Baud115200);
44 | m_serial->setDataBits(QSerialPort::Data8);
45 | m_serial->setParity(QSerialPort::NoParity);
46 | m_serial->setStopBits(QSerialPort::OneStop);
47 | m_serial->setFlowControl(QSerialPort::NoFlowControl);
48 |
49 | if (!m_serial->open(QIODevice::ReadWrite)) {
50 | emit error(tr("Can't open %1, error code %2")
51 | .arg(m_portName).arg(m_serial->error()));
52 | return;
53 | }
54 |
55 | emit info(tr("Sending Hello to the Bootloader...\n"));
56 |
57 | //send HELLO
58 | QByteArray currentRequest;
59 | currentRequest.append(BOOTLOADER_HELLO_STR);
60 | QByteArray responseData=sendCommandAndWaitForResponse(currentRequest,10);
61 |
62 | //qDebug() << responseData;
63 |
64 | if( responseData.size() != 1 || responseData.at(0) != BOOTLOADER_OK ) {
65 | emit error(tr("Bootloader did not reply."));
66 | }
67 |
68 | /* if( (unsigned char)responseData.at(0) != PIC_ID ) {
69 | emit error(tr("Wrong chip ID."));
70 | }
71 | */
72 | emit info(tr("OK\n"));
73 |
74 | //send the firmware
75 | qint32 res=sendFirmware(blob);
76 |
77 | if( res == 0 ) {
78 | emit info("\nFirmware updated successfully :)!\n\n");
79 | emit info("\nLoading FPGA\n");
80 |
81 | currentRequest.clear();
82 | currentRequest.append(0x03);
83 | responseData=sendCommandAndWaitForResponse(currentRequest,1000);
84 |
85 | if(responseData.size()==0 || responseData.at(0)!=BOOTLOADER_OK){
86 | emit info("failed!\n");
87 | }
88 | emit info("ok\n");
89 | } else {
90 | emit info("\nError updating firmware :(\n\n");
91 | }
92 |
93 |
94 | m_serial->close();
95 |
96 | emit finished();
97 |
98 | }
99 |
100 |
101 | qint32 loadIce40::sendFirmware(QByteArray blob){
102 |
103 | qint32 u_addr=0;
104 | quint32 page = 0;
105 | qint32 done = 0;
106 | quint32 row = 0;
107 |
108 | QByteArray command;
109 |
110 | //add blob size to first three bytes MSB
111 | u_addr=blob.size();
112 | blob.prepend((char) ((u_addr & 0x00FF0000) >> 16 ));
113 | blob.prepend((char) ((u_addr & 0x0000FF00) >> 8 ));
114 | blob.prepend((char) ((u_addr & 0x000000FF) >> 0 ));
115 | u_addr=0;
116 |
117 | //write 8 rows
118 | for( page = 0; u_addr> 16 ));
123 | command.append( (char) ((u_addr & 0x0000FF00) >> 8 ));
124 | command.append( (char) ((u_addr & 0x000000FF) >> 0));
125 | //command.append( char(PIC_ROW_SIZE + 0x01)); //DATA_LENGTH + CRC
126 | command.append(blob.mid(u_addr,256));
127 | if(u_addr+256>blob.size()){
128 | command.append((u_addr+256)-blob.size(), (char)0xff);
129 | qDebug()<< command.size();
130 | }
131 | //command.append( (char) makeCrc(command));
132 |
133 | emit info(QString("Writing page %1, %3...").arg(page).arg(u_addr,1,16).toLatin1());
134 |
135 | QByteArray responseData=sendCommandAndWaitForResponse(command,10);
136 | //qDebug()<write(currentRequest);
159 | if (m_serial->waitForBytesWritten(delay*10)) {
160 | // read response
161 | if (m_serial->waitForReadyRead(delay*10)) {
162 | responseData = m_serial->readAll();
163 | while (m_serial->waitForReadyRead(delay))
164 | responseData += m_serial->readAll();
165 | } else {
166 | emit info(tr("Wait read response timeout %1")
167 | .arg(QTime::currentTime().toString()));
168 | }
169 | } else {
170 | emit info(tr("Wait write request timeout %1")
171 | .arg(QTime::currentTime().toString()));
172 | }
173 | return responseData;
174 | }
175 |
176 | quint8 loadIce40::makeCrc(QByteArray buf)
177 | {
178 | quint8 crc = 0, i = 0;
179 |
180 | for(i=0; i
8 | #include
9 | #include
10 |
11 | #include "load-image.h"
12 |
13 | loadImageWorker::loadImageWorker(const QString &portName, const QString &fileName)
14 | {
15 | m_portName = portName;
16 | m_filename=fileName;
17 | }
18 |
19 | loadImageWorker::~loadImageWorker()
20 | {
21 | }
22 |
23 | void loadImageWorker::load()
24 | {
25 | qDebug() <<"Worker::loadImage called from: " << QThread::currentThreadId();
26 |
27 | QImage img;
28 | img.load(m_filename);
29 | qDebug() << img.width() << img.height();
30 | img=img.convertToFormat(QImage::Format_RGB16);
31 | QByteArray blob = QByteArray::fromRawData(reinterpret_cast(img.constBits()), img.sizeInBytes());
32 | //QByteArray blob;
33 | //uchar *bits = img.bits();
34 |
35 | qDebug() << img.width() << img.height() << blob.size();
36 |
37 | /*for (int i = 0; i < (img.width() * img.height() * 3); i++)
38 | {
39 | blob.append(reinterpret_cast(bits[i]));
40 | }*/
41 |
42 |
43 | //QString outputError=tr("\nBitstream %1 is %2 bytes.\n").arg(m_filename).arg(file.size());
44 | //emit info(outputError);
45 |
46 | m_serial = new QSerialPort;
47 |
48 | if (m_portName.isEmpty()) {
49 | emit error(tr("No port name specified"));
50 | return;
51 | }
52 |
53 | m_serial->close();
54 | m_serial->setPortName(m_portName);
55 | m_serial->setBaudRate(921600);//QSerialPort::Baud115200);
56 | m_serial->setDataBits(QSerialPort::Data8);
57 | m_serial->setParity(QSerialPort::NoParity);
58 | m_serial->setStopBits(QSerialPort::OneStop);
59 | m_serial->setFlowControl(QSerialPort::NoFlowControl);
60 |
61 | if (!m_serial->open(QIODevice::ReadWrite)) {
62 | emit error(tr("Can't open %1, error code %2")
63 | .arg(m_portName).arg(m_serial->error()));
64 | return;
65 | }
66 |
67 | emit info(tr("Sending Hello to the Bootloader...\n"));
68 |
69 | //send HELLO
70 | QByteArray currentRequest;
71 | currentRequest.append(BOOTLOADER_HELLO_STR);
72 | QByteArray responseData=sendCommandAndWaitForResponse(currentRequest,10);
73 |
74 | //qDebug() << responseData;
75 |
76 | if( responseData.size() != 1 || responseData.at(0) != BOOTLOADER_OK ) {
77 | emit error(tr("Bootloader did not reply."));
78 | }
79 |
80 | /* if( (unsigned char)responseData.at(0) != PIC_ID ) {
81 | emit error(tr("Wrong chip ID."));
82 | }
83 | */
84 | emit info(tr("OK\n"));
85 |
86 | //send the firmware
87 | qint32 res=sendFirmware(blob);
88 |
89 | if( res == 0 ) {
90 | emit info("\nImage updated successfully :)!\n\n");
91 | emit info("\nUpdating display...");
92 | currentRequest.clear();
93 | currentRequest.append(0x05);
94 | responseData=sendCommandAndWaitForResponse(currentRequest,10000);
95 |
96 | if(responseData.size()==0 || responseData.at(0)!=BOOTLOADER_OK){
97 | emit info("failed!\n");
98 | }
99 | emit info("ok\n");
100 | } else {
101 | emit info("\nError updating image :(\n\n");
102 | }
103 |
104 |
105 | m_serial->close();
106 |
107 | emit finished();
108 |
109 | }
110 |
111 | qint32 loadImageWorker::sendFirmware(QByteArray blob){
112 |
113 | qint32 u_addr=0;
114 | quint32 page = 0;
115 | qint32 done = 0;
116 | quint32 row = 0;
117 |
118 | QByteArray command;
119 |
120 | //add blob size to first three bytes MSB
121 | u_addr=blob.size();
122 | //blob.prepend((char) ((u_addr & 0x00FF0000) >> 16 ));
123 | //blob.prepend((char) ((u_addr & 0x0000FF00) >> 8 ));
124 | //blob.prepend((char) ((u_addr & 0x000000FF) >> 0 ));
125 | u_addr=0;
126 |
127 | //write 8 rows
128 | for( page = 0; u_addr> 16 ));
133 | command.append( (char) ((u_addr & 0x0000FF00) >> 8 ));
134 | command.append( (char) ((u_addr & 0x000000FF) >> 0));
135 | //command.append( char(PIC_ROW_SIZE + 0x01)); //DATA_LENGTH + CRC
136 | command.append(blob.mid(u_addr,256));
137 | if(u_addr+256>blob.size()){
138 | command.append((u_addr+256)-blob.size(), (char)0xff);
139 | qDebug()<< command.size();
140 | }
141 | //command.append( (char) makeCrc(command));
142 |
143 | emit info(QString("Writing page %1, %3...").arg(page).arg(u_addr,1,16).toLatin1());
144 |
145 |
146 | //qDebug() << command.toHex(',');
147 |
148 | QByteArray responseData=sendCommandAndWaitForResponse(command,10);
149 | //qDebug()<write(currentRequest);
172 | if (m_serial->waitForBytesWritten(delay*10)) {
173 | // read response
174 | if (m_serial->waitForReadyRead(delay*10)) {
175 | responseData = m_serial->readAll();
176 | while (m_serial->waitForReadyRead(delay))
177 | responseData += m_serial->readAll();
178 | } else {
179 | emit info(tr("Wait read response timeout %1")
180 | .arg(QTime::currentTime().toString()));
181 | }
182 | } else {
183 | emit info(tr("Wait write request timeout %1")
184 | .arg(QTime::currentTime().toString()));
185 | }
186 | return responseData;
187 | }
188 |
189 |
190 | #endif
191 |
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2016 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #ifndef MAINWINDOW_H
52 | #define MAINWINDOW_H
53 |
54 | #include
55 | #include
56 | #include "qcustomplot.h"
57 |
58 | QT_BEGIN_NAMESPACE
59 | class QAction;
60 | class QMenu;
61 | class QLabel;
62 | //class QDeviceWatcher;
63 | QT_END_NAMESPACE
64 |
65 | class Console;
66 | class SettingsDialog;
67 |
68 | class MainWindow : public QMainWindow
69 | {
70 | Q_OBJECT
71 |
72 | public:
73 | MainWindow();
74 |
75 | private slots:
76 | void save();
77 | void print();
78 | void about();
79 | void openSerialPort(bool reconnect);
80 | void closeSerialPort(bool reconnect);
81 | void writeData(const QByteArray &data);
82 | void readData();
83 | void showPortInfo(int idx);
84 | void handleError(QSerialPort::SerialPortError error);
85 | void convert(const QString &text);
86 | //void horzScrollBarChanged(int value);
87 | void lockRange(QCPRange range);
88 | void fillPortsInfo();
89 | //void serialPortChanged(const QString &text);
90 | //void transaction();
91 | void consoleLog(const QString &s);
92 | void processError(const QString &s);
93 | void processTimeout(const QString &s);
94 | void processBootload(const QByteArray &firmware);
95 | void openBitstreamFile();
96 | void openFirmwareFile();
97 | void openImageFile();
98 | void openFontFile();
99 | void fwUpdateProgress(const quint8 &c);
100 | void bsUpdateProgress(const quint8 &c);
101 | void imageUpdateProgress(const quint8 &c);
102 | void bsComplete();
103 | void periodicEvents();
104 | void binaryModeReadData();
105 | void binaryModeConnect();
106 |
107 | protected:
108 | bool eventFilter(QObject *obj, QEvent *event);
109 |
110 | private:
111 | void createActions();
112 | void createStatusBar();
113 | void createDockWindows();
114 | void showStatusMessage(const QString &message);
115 | void analyseFile(const QString &fileName);
116 | void loadBitstream(const QString &fileName);
117 | void loadImage(const QString &fileName);
118 |
119 | QDockWidget *laDock;
120 |
121 | //serial port stuff
122 | struct Settings {
123 | QString name;
124 | qint32 baudRate;
125 | QString stringBaudRate;
126 | QSerialPort::DataBits dataBits;
127 | QString stringDataBits;
128 | QSerialPort::Parity parity;
129 | QString stringParity;
130 | QSerialPort::StopBits stopBits;
131 | QString stringStopBits;
132 | QSerialPort::FlowControl flowControl;
133 | QString stringFlowControl;
134 | bool localEchoEnabled;
135 | };
136 | QLabel *m_status = nullptr;
137 | Console *m_console = nullptr;
138 | //SettingsDialog *m_settings = nullptr;
139 | QSerialPort *m_serial = nullptr;
140 | //QDeviceWatcher *serialPortWatcher;
141 |
142 | QMenu *viewMenu;
143 | QCustomPlot *m_customPlot;
144 | QLineEdit *echoLineEdit;
145 | QLineEdit *conv_dec;
146 | QLineEdit *conv_hex;
147 | QLineEdit *conv_bin;
148 | QLineEdit *conv_ascii;
149 |
150 | QComboBox *serialPortInfoListBox;
151 | QLabel *serialPortDescriptionLabel;
152 | QLabel *serialPortLocationLabel;
153 | QLabel *serialPortManufacturerLabel;
154 | QLabel *serialPortPidLabel;
155 | QLabel *serialPortSerialNumberLabel;
156 | QLabel *serialPortVidLabel;
157 | QCheckBox *serialPortAutoReconnect;
158 | QString serialPortReconnectName;
159 |
160 | QSerialPort *m_serialBinaryMode = nullptr;
161 | QComboBox *serialPortInfoListBoxBinaryMode;
162 | QByteArray m_logicAnalyzerSamples;
163 | quint16 m_logicAnalyzerSamplesExpected;
164 | double m_logicAnalyzerUpperBound;
165 | QPushButton *m_logicAnalyzerButton;
166 |
167 | //always running UI update timer for use in auto connect and auto updates
168 | QTimer *periodicTimer;
169 | // firmware update dock
170 | QProgressBar *m_fwUpdateProgressBar;
171 | QLabel * m_fwUpdateFileLabel;
172 | QCheckBox *m_fwUpdateAutoCheckBox;
173 | QString curFirmwareFile;
174 | QDateTime curFirmwareDateTime;
175 | //bitstream update dock
176 | QProgressBar *m_bsUpdateProgressBar;
177 | QLabel * m_bsUpdateFileLabel;
178 | QCheckBox *m_bsUpdateAutoCheckBox;
179 | QString curBitstreamFile;
180 | QDateTime curBitstreamDateTime;
181 | //image loader
182 | QProgressBar *m_imageUpdateProgressBar;
183 | QLabel * m_imageUpdateFileLabel;
184 | QString curImageFile;
185 | QLabel * m_imageLabel;
186 |
187 | bool m_bsComplete;
188 |
189 | QString curFile;
190 | QString curPath;
191 |
192 | QAction *connectAct;
193 | QAction *disconnectAct;
194 | QAction *clearAct;
195 |
196 | QVector serialPortsInfo;
197 | QStringList serialPorts;
198 | QString selectedPort;
199 | };
200 | #endif
201 |
--------------------------------------------------------------------------------
/settingsdialog.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Copyright (C) 2012 Laszlo Papp
5 | ** Contact: https://www.qt.io/licensing/
6 | **
7 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
8 | **
9 | ** $QT_BEGIN_LICENSE:BSD$
10 | ** Commercial License Usage
11 | ** Licensees holding valid commercial Qt licenses may use this file in
12 | ** accordance with the commercial license agreement provided with the
13 | ** Software or, alternatively, in accordance with the terms contained in
14 | ** a written agreement between you and The Qt Company. For licensing terms
15 | ** and conditions see https://www.qt.io/terms-conditions. For further
16 | ** information use the contact form at https://www.qt.io/contact-us.
17 | **
18 | ** BSD License Usage
19 | ** Alternatively, you may use this file under the terms of the BSD license
20 | ** as follows:
21 | **
22 | ** "Redistribution and use in source and binary forms, with or without
23 | ** modification, are permitted provided that the following conditions are
24 | ** met:
25 | ** * Redistributions of source code must retain the above copyright
26 | ** notice, this list of conditions and the following disclaimer.
27 | ** * Redistributions in binary form must reproduce the above copyright
28 | ** notice, this list of conditions and the following disclaimer in
29 | ** the documentation and/or other materials provided with the
30 | ** distribution.
31 | ** * Neither the name of The Qt Company Ltd nor the names of its
32 | ** contributors may be used to endorse or promote products derived
33 | ** from this software without specific prior written permission.
34 | **
35 | **
36 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
47 | **
48 | ** $QT_END_LICENSE$
49 | **
50 | ****************************************************************************/
51 |
52 | #include "settingsdialog.h"
53 | #include "ui_settingsdialog.h"
54 |
55 | #include
56 | #include
57 | #include
58 |
59 | static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A");
60 |
61 | SettingsDialog::SettingsDialog(QWidget *parent) :
62 | QDialog(parent),
63 | m_ui(new Ui::SettingsDialog),
64 | m_intValidator(new QIntValidator(0, 4000000, this))
65 | {
66 | m_ui->setupUi(this);
67 |
68 | m_ui->baudRateBox->setInsertPolicy(QComboBox::NoInsert);
69 |
70 | connect(m_ui->applyButton, &QPushButton::clicked,
71 | this, &SettingsDialog::apply);
72 | connect(m_ui->serialPortInfoListBox, QOverload::of(&QComboBox::currentIndexChanged),
73 | this, &SettingsDialog::showPortInfo);
74 | connect(m_ui->baudRateBox, QOverload::of(&QComboBox::currentIndexChanged),
75 | this, &SettingsDialog::checkCustomBaudRatePolicy);
76 | connect(m_ui->serialPortInfoListBox, QOverload::of(&QComboBox::currentIndexChanged),
77 | this, &SettingsDialog::checkCustomDevicePathPolicy);
78 |
79 | fillPortsParameters();
80 | fillPortsInfo();
81 |
82 | updateSettings();
83 | }
84 |
85 | SettingsDialog::~SettingsDialog()
86 | {
87 | delete m_ui;
88 | }
89 |
90 | SettingsDialog::Settings SettingsDialog::settings() const
91 | {
92 | return m_currentSettings;
93 | }
94 |
95 | void SettingsDialog::showPortInfo(int idx)
96 | {
97 | if (idx == -1)
98 | return;
99 |
100 | const QStringList list = m_ui->serialPortInfoListBox->itemData(idx).toStringList();
101 | m_ui->descriptionLabel->setText(tr("Description: %1").arg(list.count() > 1 ? list.at(1) : tr(blankString)));
102 | m_ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.count() > 2 ? list.at(2) : tr(blankString)));
103 | m_ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.count() > 3 ? list.at(3) : tr(blankString)));
104 | m_ui->locationLabel->setText(tr("Location: %1").arg(list.count() > 4 ? list.at(4) : tr(blankString)));
105 | m_ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.count() > 5 ? list.at(5) : tr(blankString)));
106 | m_ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.count() > 6 ? list.at(6) : tr(blankString)));
107 | }
108 |
109 | void SettingsDialog::apply()
110 | {
111 | updateSettings();
112 | hide();
113 | }
114 |
115 | void SettingsDialog::checkCustomBaudRatePolicy(int idx)
116 | {
117 | const bool isCustomBaudRate = !m_ui->baudRateBox->itemData(idx).isValid();
118 | m_ui->baudRateBox->setEditable(isCustomBaudRate);
119 | if (isCustomBaudRate) {
120 | m_ui->baudRateBox->clearEditText();
121 | QLineEdit *edit = m_ui->baudRateBox->lineEdit();
122 | edit->setValidator(m_intValidator);
123 | }
124 | }
125 |
126 | void SettingsDialog::checkCustomDevicePathPolicy(int idx)
127 | {
128 | const bool isCustomPath = !m_ui->serialPortInfoListBox->itemData(idx).isValid();
129 | m_ui->serialPortInfoListBox->setEditable(isCustomPath);
130 | if (isCustomPath)
131 | m_ui->serialPortInfoListBox->clearEditText();
132 | }
133 |
134 | void SettingsDialog::fillPortsParameters()
135 | {
136 | m_ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
137 | m_ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
138 | m_ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
139 | m_ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
140 | m_ui->baudRateBox->addItem(tr("Custom"));
141 |
142 | m_ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5);
143 | m_ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6);
144 | m_ui->dataBitsBox->addItem(QStringLiteral("7"), QSerialPort::Data7);
145 | m_ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8);
146 | m_ui->dataBitsBox->setCurrentIndex(3);
147 |
148 | m_ui->parityBox->addItem(tr("None"), QSerialPort::NoParity);
149 | m_ui->parityBox->addItem(tr("Even"), QSerialPort::EvenParity);
150 | m_ui->parityBox->addItem(tr("Odd"), QSerialPort::OddParity);
151 | m_ui->parityBox->addItem(tr("Mark"), QSerialPort::MarkParity);
152 | m_ui->parityBox->addItem(tr("Space"), QSerialPort::SpaceParity);
153 |
154 | m_ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop);
155 | #ifdef Q_OS_WIN
156 | m_ui->stopBitsBox->addItem(tr("1.5"), QSerialPort::OneAndHalfStop);
157 | #endif
158 | m_ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop);
159 |
160 | m_ui->flowControlBox->addItem(tr("None"), QSerialPort::NoFlowControl);
161 | m_ui->flowControlBox->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
162 | m_ui->flowControlBox->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);
163 | }
164 |
165 | QList SettingsDialog::fillPortsInfo()
166 | {
167 | //m_ui->serialPortInfoListBox->clear();
168 | QList portList;
169 | QString description;
170 | QString manufacturer;
171 | QString serialNumber;
172 | const auto infos = QSerialPortInfo::availablePorts();
173 | for (const QSerialPortInfo &info : infos) {
174 | QStringList list;
175 | description = info.description();
176 | manufacturer = info.manufacturer();
177 | serialNumber = info.serialNumber();
178 | list << info.portName()
179 | << (!description.isEmpty() ? description : blankString)
180 | << (!manufacturer.isEmpty() ? manufacturer : blankString)
181 | << (!serialNumber.isEmpty() ? serialNumber : blankString)
182 | << info.systemLocation()
183 | << (info.vendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : blankString)
184 | << (info.productIdentifier() ? QString::number(info.productIdentifier(), 16) : blankString);
185 |
186 | portList.append(list);
187 | //m_ui->serialPortInfoListBox->addItem(list.first(), list);
188 | }
189 |
190 | return portList;
191 | //m_ui->serialPortInfoListBox->addItem(tr("Custom"));
192 | }
193 |
194 | void SettingsDialog::updateSettings()
195 | {
196 | m_currentSettings.name = m_ui->serialPortInfoListBox->currentText();
197 |
198 | if (m_ui->baudRateBox->currentIndex() == 4) {
199 | m_currentSettings.baudRate = m_ui->baudRateBox->currentText().toInt();
200 | } else {
201 | m_currentSettings.baudRate = static_cast(
202 | m_ui->baudRateBox->itemData(m_ui->baudRateBox->currentIndex()).toInt());
203 | }
204 | m_currentSettings.stringBaudRate = QString::number(m_currentSettings.baudRate);
205 |
206 | m_currentSettings.dataBits = static_cast(
207 | m_ui->dataBitsBox->itemData(m_ui->dataBitsBox->currentIndex()).toInt());
208 | m_currentSettings.stringDataBits = m_ui->dataBitsBox->currentText();
209 |
210 | m_currentSettings.parity = static_cast(
211 | m_ui->parityBox->itemData(m_ui->parityBox->currentIndex()).toInt());
212 | m_currentSettings.stringParity = m_ui->parityBox->currentText();
213 |
214 | m_currentSettings.stopBits = static_cast(
215 | m_ui->stopBitsBox->itemData(m_ui->stopBitsBox->currentIndex()).toInt());
216 | m_currentSettings.stringStopBits = m_ui->stopBitsBox->currentText();
217 |
218 | m_currentSettings.flowControl = static_cast(
219 | m_ui->flowControlBox->itemData(m_ui->flowControlBox->currentIndex()).toInt());
220 | m_currentSettings.stringFlowControl = m_ui->flowControlBox->currentText();
221 |
222 | m_currentSettings.localEchoEnabled = m_ui->localEchoCheckBox->isChecked();
223 | }
224 |
--------------------------------------------------------------------------------
/loader-ds30loader.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2012 Denis Shienkov
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 | /* macro definitions */
51 | #define BOOTLOADER_HELLO_STR "\xC1"
52 | #define BOOTLOADER_OK 0x4B
53 | #define BOOTLOADER_PLACEMENT 1
54 |
55 | #define PIC_ID 0xD4
56 | #define PIC_FLASHSIZE 0xAC00
57 |
58 | #define PIC_NUM_PAGES 42
59 | #define PIC_NUM_ROWS_IN_PAGE 8
60 | #define PIC_NUM_WORDS_IN_ROW 64
61 |
62 | #define PIC_WORD_SIZE (3)
63 | #define PIC_ROW_SIZE (PIC_NUM_WORDS_IN_ROW * PIC_WORD_SIZE)
64 | #define PIC_PAGE_SIZE (PIC_NUM_ROWS_IN_PAGE * PIC_ROW_SIZE)
65 |
66 | #define PIC_ROW_ADDR(p,r) (((p) * PIC_PAGE_SIZE) + ((r) * PIC_ROW_SIZE))
67 | #define PIC_WORD_ADDR(p,r,w) (PIC_ROW_ADDR(p,r) + ((w) * PIC_WORD_SIZE))
68 | #define PIC_PAGE_ADDR(p) (PIC_PAGE_SIZE * (p))
69 |
70 | #define ADDR_24 0
71 | #define ADDR_16 1
72 | #define ADDR_8 2
73 | #define COMMAND_OFFSET 3
74 | #define LENGTH_OFFSET 4
75 | #define PAYLOAD_OFFSET 5
76 | #define HEADER_LENGTH PAYLOAD_OFFSET
77 |
78 | #include "loader-ds30loader.h"
79 |
80 | #include
81 | #include
82 | #include
83 |
84 | loaderds30loader::loaderds30loader(const QString &portName, const QByteArray &firmware)
85 | {
86 | m_portName = portName;
87 | m_firmware=firmware;
88 |
89 | }
90 |
91 | loaderds30loader::~loaderds30loader()
92 | {
93 | }
94 |
95 |
96 | void loaderds30loader::load()
97 | {
98 |
99 | qDebug()<<"Worker::loaderds30loader called from: "<close();
109 | m_serial->setPortName(m_portName);
110 | m_serial->setBaudRate(QSerialPort::Baud115200);
111 | m_serial->setDataBits(QSerialPort::Data8);
112 | m_serial->setParity(QSerialPort::NoParity);
113 | m_serial->setStopBits(QSerialPort::OneStop);
114 | m_serial->setFlowControl(QSerialPort::NoFlowControl);
115 |
116 | if (!m_serial->open(QIODevice::ReadWrite)) {
117 | emit error(tr("Can't open %1, error code %2")
118 | .arg(m_portName).arg(m_serial->error()));
119 | return;
120 | }
121 |
122 | emit info(tr("Sending Hello to the Bootloader...\n"));
123 |
124 | //send HELLO
125 | QByteArray currentRequest;
126 | currentRequest.append(BOOTLOADER_HELLO_STR);
127 | QByteArray responseData=sendCommandAndWaitForResponse(currentRequest);
128 |
129 | //qDebug() << responseData;
130 |
131 | if( responseData.size() != 4 || responseData.at(3) != BOOTLOADER_OK ) {
132 | emit error(tr("Bootloader did not reply."));
133 | }
134 |
135 | if( (unsigned char)responseData.at(0) != PIC_ID ) {
136 | emit error(tr("Wrong chip ID."));
137 | }
138 |
139 | emit info(tr("OK\n"));
140 |
141 | // get the raw HEX into proper format
142 | QByteArray byteStream;
143 | for(int i=0; i> 8 ),
165 | '\x00',
166 | (char)( (iBLAddress & 0x7F0000) >> 16 ),
167 | '\x00'};
168 |
169 | byteStream.replace(0,6, jump, sizeof(jump));
170 | //}
171 |
172 | //send the firmware
173 | qint32 res=sendFirmware(byteStream);
174 |
175 | if( res > 0 ) {
176 | emit info("\nFirmware updated successfully :)!\n\n");
177 | } else {
178 | emit info("\nError updating firmware :(\n\n");
179 | }
180 |
181 | m_serial->close();
182 |
183 | emit finished();
184 |
185 | }
186 |
187 |
188 | qint32 loaderds30loader::sendFirmware(QByteArray firmware){
189 |
190 | quint32 u_addr;
191 | quint32 page = 0;
192 | qint32 done = 0;
193 | quint32 row = 0;
194 |
195 | QByteArray command;
196 |
197 |
198 |
199 | for( page=0; page= PIC_FLASHSIZE ) {
203 | emit error(tr("Address out of flash\n"));
204 | return -1;
205 | }
206 |
207 | //erase page
208 | command.clear();
209 | command.append( (char)((u_addr & 0x00FF0000) >> 16) );
210 | command.append( (char)((u_addr & 0x0000FF00) >> 8) );
211 | command.append( (char)((u_addr & 0x000000FF) >> 0));
212 | command.append( 0x01); //erase command
213 | command.append( 0x01); //1 byte, CRC
214 | command.append( (char) makeCrc(command) );
215 |
216 | emit info(QString("Erasing page %1, %2...").arg(page).arg(u_addr,1,16).toLatin1());
217 |
218 | QByteArray responseData=sendCommandAndWaitForResponse(command);
219 | //qDebug()<> 16 ));
232 | command.append( (char) ((u_addr & 0x0000FF00) >> 8 ));
233 | command.append( (char) ((u_addr & 0x000000FF) >> 0));
234 | command.append( 0x02); //write command
235 | command.append( char(PIC_ROW_SIZE + 0x01)); //DATA_LENGTH + CRC
236 | command.append(firmware.mid((int)PIC_ROW_ADDR(page, row),PIC_ROW_SIZE));
237 | command.append( (char) makeCrc(command));
238 |
239 | emit info(QString("Writing page %1 row %2, %3...").arg(page).arg(row+page*PIC_NUM_ROWS_IN_PAGE).arg(u_addr,1,16).toLatin1());
240 |
241 | QByteArray responseData=sendCommandAndWaitForResponse(command);
242 | //qDebug()<write(currentRequest);
265 | if (m_serial->waitForBytesWritten(10000)) {
266 | // read response
267 | if (m_serial->waitForReadyRead(1000)) {
268 | responseData = m_serial->readAll();
269 | while (m_serial->waitForReadyRead(10))
270 | responseData += m_serial->readAll();
271 | } else {
272 | emit timeout(tr("Wait read response timeout %1")
273 | .arg(QTime::currentTime().toString()));
274 | }
275 | } else {
276 | emit timeout(tr("Wait write request timeout %1")
277 | .arg(QTime::currentTime().toString()));
278 | }
279 | return responseData;
280 | }
281 |
282 | quint8 loaderds30loader::makeCrc(QByteArray buf)
283 | {
284 | quint8 crc = 0, i = 0;
285 |
286 | for(i=0; i
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the QtSerialPort module of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 | /* macro definitions */
51 | #define BOOTLOADER_HELLO_STR "\xC1"
52 | #define BOOTLOADER_OK 0x4B
53 | #define BOOTLOADER_PLACEMENT 1
54 |
55 | #define PIC_ID 0xD4
56 | #define PIC_FLASHSIZE 0xAC00
57 |
58 | #define PIC_NUM_PAGES 42
59 | #define PIC_NUM_ROWS_IN_PAGE 8
60 | #define PIC_NUM_WORDS_IN_ROW 64
61 |
62 | #define PIC_WORD_SIZE (3)
63 | #define PIC_ROW_SIZE (PIC_NUM_WORDS_IN_ROW * PIC_WORD_SIZE)
64 | #define PIC_PAGE_SIZE (PIC_NUM_ROWS_IN_PAGE * PIC_ROW_SIZE)
65 |
66 | #define PIC_ROW_ADDR(p,r) (((p) * PIC_PAGE_SIZE) + ((r) * PIC_ROW_SIZE))
67 | #define PIC_WORD_ADDR(p,r,w) (PIC_ROW_ADDR(p,r) + ((w) * PIC_WORD_SIZE))
68 | #define PIC_PAGE_ADDR(p) (PIC_PAGE_SIZE * (p))
69 |
70 | #define ADDR_24 0
71 | #define ADDR_16 1
72 | #define ADDR_8 2
73 | #define COMMAND_OFFSET 3
74 | #define LENGTH_OFFSET 4
75 | #define PAYLOAD_OFFSET 5
76 | #define HEADER_LENGTH PAYLOAD_OFFSET
77 |
78 | #include "programthread.h"
79 |
80 | #include
81 | #include
82 | #include
83 |
84 | programthread::programthread(QObject *parent) :
85 | QThread(parent)
86 | {
87 | }
88 |
89 | programthread::~programthread()
90 | {
91 | m_mutex.lock();
92 | m_quit = true;
93 | m_cond.wakeOne();
94 | m_mutex.unlock();
95 | wait();
96 | }
97 |
98 | void programthread::transaction(const QString &portName, QByteArray &firmware)
99 | {
100 |
101 | const QMutexLocker locker(&m_mutex);
102 | m_portName = portName;
103 | m_firmware=firmware;
104 |
105 | if (!isRunning())
106 | start();
107 | else
108 | m_cond.wakeOne();
109 | }
110 |
111 |
112 |
113 |
114 | QByteArray programthread::sendCommandAndWaitForResponse(QByteArray currentRequest){
115 | QByteArray responseData;
116 | m_serial->write(currentRequest);
117 | if (m_serial->waitForBytesWritten(10000)) {
118 | // read response
119 | if (m_serial->waitForReadyRead(1000)) {
120 | responseData = m_serial->readAll();
121 | while (m_serial->waitForReadyRead(10))
122 | responseData += m_serial->readAll();
123 | } else {
124 | emit timeout(tr("Wait read response timeout %1")
125 | .arg(QTime::currentTime().toString()));
126 | }
127 | } else {
128 | emit timeout(tr("Wait write request timeout %1")
129 | .arg(QTime::currentTime().toString()));
130 | }
131 | return responseData;
132 | }
133 |
134 | quint8 programthread::makeCrc(QByteArray buf)
135 | {
136 | quint8 crc = 0, i = 0;
137 |
138 | for(i=0; iclose();
180 | m_serial->setPortName(currentPortName);
181 | m_serial->setBaudRate(QSerialPort::Baud115200);
182 | m_serial->setDataBits(QSerialPort::Data8);
183 | m_serial->setParity(QSerialPort::NoParity);
184 | m_serial->setStopBits(QSerialPort::OneStop);
185 | m_serial->setFlowControl(QSerialPort::NoFlowControl);
186 |
187 | if (!m_serial->open(QIODevice::ReadWrite)) {
188 | emit error(tr("Can't open %1, error code %2")
189 | .arg(m_portName).arg(m_serial->error()));
190 | return;
191 | }
192 | }
193 |
194 | emit info(tr("Sending Hello to the Bootloader...\n"));
195 |
196 | //send HELLO
197 | QByteArray currentRequest;
198 | currentRequest.append(BOOTLOADER_HELLO_STR);
199 | QByteArray responseData=sendCommandAndWaitForResponse(currentRequest);
200 |
201 | qDebug() << responseData;
202 |
203 | if( responseData.size() != 4 || responseData.at(3) != BOOTLOADER_OK ) {
204 | emit error(tr("Bootloader did not reply."));
205 | }
206 |
207 | if( (unsigned char)responseData.at(0) != PIC_ID ) {
208 | emit error(tr("Wrong chip ID."));
209 | }
210 |
211 | emit info(tr("OK\n"));
212 |
213 | qint32 res=sendFirmware(m_firmware);
214 |
215 | if( res > 0 ) {
216 | emit info("\nFirmware updated successfully :)!");
217 | } else {
218 | emit info("\nError updating firmware :(");
219 | }
220 |
221 | m_mutex.lock();
222 | m_cond.wait(&m_mutex);
223 | if (currentPortName != m_portName) {
224 | currentPortName = m_portName;
225 | currentPortNameChanged = true;
226 | } else {
227 | currentPortNameChanged = false;
228 | }
229 | //currentWaitTimeout = m_waitTimeout;
230 | //currentRequest = m_request;
231 | firmware = m_firmware;
232 | m_mutex.unlock();
233 | }
234 |
235 | }
236 |
237 | qint32 programthread::sendFirmware(QByteArray firmware){
238 |
239 | quint32 u_addr;
240 | quint32 page = 0;
241 | qint32 done = 0;
242 | quint32 row = 0;
243 |
244 | quint32 prog, denom;
245 |
246 | QByteArray command;
247 |
248 | qDebug()<<"Worker::sendFirmware get called from?: "<= PIC_FLASHSIZE ) {
254 | emit error(tr("Address out of flash\n"));
255 | return -1;
256 | }
257 |
258 | //erase page
259 | command.clear();
260 | command.append( (char)((u_addr & 0x00FF0000) >> 16) );
261 | command.append( (char)((u_addr & 0x0000FF00) >> 8) );
262 | command.append( (char)((u_addr & 0x000000FF) >> 0));
263 | command.append( 0x01); //erase command
264 | command.append( 0x01); //1 byte, CRC
265 | command.append( (char) makeCrc(command) );
266 |
267 |
268 | //if( g_verbose ) {
269 | //dumpHex(command, HEADER_LENGTH + command[LENGTH_OFFSET]);
270 | //}
271 |
272 | emit info(QString("Erasing page %1, %2...").arg(page).arg(u_addr,1,16).toLatin1());
273 |
274 | QByteArray responseData=sendCommandAndWaitForResponse(command);
275 | //qDebug()<> 16 ));
292 | command.append( (char) ((u_addr & 0x0000FF00) >> 8 ));
293 | command.append( (char) ((u_addr & 0x000000FF) >> 0));
294 | command.append( 0x02); //write command
295 | command.append( char(PIC_ROW_SIZE + 0x01)); //DATA_LENGTH + CRC
296 | command.append(firmware.mid((int)PIC_ROW_ADDR(page, row),PIC_ROW_SIZE));
297 | command.append( (char) makeCrc(command));
298 |
299 | emit info(QString("Writing page %1 row %2, %3...").arg(page).arg(row+page*PIC_NUM_ROWS_IN_PAGE).arg(u_addr,1,16).toLatin1());
300 |
301 | QByteArray responseData=sendCommandAndWaitForResponse(command);
302 | //qDebug()<
17 | Everyone is permitted to copy and distribute verbatim copies
18 | of this license document, but changing it is not allowed.
19 |
20 | Preamble
21 |
22 | The GNU General Public License is a free, copyleft license for
23 | software and other kinds of works.
24 |
25 | The licenses for most software and other practical works are designed
26 | to take away your freedom to share and change the works. By contrast,
27 | the GNU General Public License is intended to guarantee your freedom to
28 | share and change all versions of a program--to make sure it remains free
29 | software for all its users. We, the Free Software Foundation, use the
30 | GNU General Public License for most of our software; it applies also to
31 | any other work released this way by its authors. You can apply it to
32 | your programs, too.
33 |
34 | When we speak of free software, we are referring to freedom, not
35 | price. Our General Public Licenses are designed to make sure that you
36 | have the freedom to distribute copies of free software (and charge for
37 | them if you wish), that you receive source code or can get it if you
38 | want it, that you can change the software or use pieces of it in new
39 | free programs, and that you know you can do these things.
40 |
41 | To protect your rights, we need to prevent others from denying you
42 | these rights or asking you to surrender the rights. Therefore, you have
43 | certain responsibilities if you distribute copies of the software, or if
44 | you modify it: responsibilities to respect the freedom of others.
45 |
46 | For example, if you distribute copies of such a program, whether
47 | gratis or for a fee, you must pass on to the recipients the same
48 | freedoms that you received. You must make sure that they, too, receive
49 | or can get the source code. And you must show them these terms so they
50 | know their rights.
51 |
52 | Developers that use the GNU GPL protect your rights with two steps:
53 | (1) assert copyright on the software, and (2) offer you this License
54 | giving you legal permission to copy, distribute and/or modify it.
55 |
56 | For the developers' and authors' protection, the GPL clearly explains
57 | that there is no warranty for this free software. For both users' and
58 | authors' sake, the GPL requires that modified versions be marked as
59 | changed, so that their problems will not be attributed erroneously to
60 | authors of previous versions.
61 |
62 | Some devices are designed to deny users access to install or run
63 | modified versions of the software inside them, although the manufacturer
64 | can do so. This is fundamentally incompatible with the aim of
65 | protecting users' freedom to change the software. The systematic
66 | pattern of such abuse occurs in the area of products for individuals to
67 | use, which is precisely where it is most unacceptable. Therefore, we
68 | have designed this version of the GPL to prohibit the practice for those
69 | products. If such problems arise substantially in other domains, we
70 | stand ready to extend this provision to those domains in future versions
71 | of the GPL, as needed to protect the freedom of users.
72 |
73 | Finally, every program is threatened constantly by software patents.
74 | States should not allow patents to restrict development and use of
75 | software on general-purpose computers, but in those that do, we wish to
76 | avoid the special danger that patents applied to a free program could
77 | make it effectively proprietary. To prevent this, the GPL assures that
78 | patents cannot be used to render the program non-free.
79 |
80 | The precise terms and conditions for copying, distribution and
81 | modification follow.
82 |
83 | TERMS AND CONDITIONS
84 |
85 | 0. Definitions.
86 |
87 | "This License" refers to version 3 of the GNU General Public License.
88 |
89 | "Copyright" also means copyright-like laws that apply to other kinds of
90 | works, such as semiconductor masks.
91 |
92 | "The Program" refers to any copyrightable work licensed under this
93 | License. Each licensee is addressed as "you". "Licensees" and
94 | "recipients" may be individuals or organizations.
95 |
96 | To "modify" a work means to copy from or adapt all or part of the work
97 | in a fashion requiring copyright permission, other than the making of an
98 | exact copy. The resulting work is called a "modified version" of the
99 | earlier work or a work "based on" the earlier work.
100 |
101 | A "covered work" means either the unmodified Program or a work based
102 | on the Program.
103 |
104 | To "propagate" a work means to do anything with it that, without
105 | permission, would make you directly or secondarily liable for
106 | infringement under applicable copyright law, except executing it on a
107 | computer or modifying a private copy. Propagation includes copying,
108 | distribution (with or without modification), making available to the
109 | public, and in some countries other activities as well.
110 |
111 | To "convey" a work means any kind of propagation that enables other
112 | parties to make or receive copies. Mere interaction with a user through
113 | a computer network, with no transfer of a copy, is not conveying.
114 |
115 | An interactive user interface displays "Appropriate Legal Notices"
116 | to the extent that it includes a convenient and prominently visible
117 | feature that (1) displays an appropriate copyright notice, and (2)
118 | tells the user that there is no warranty for the work (except to the
119 | extent that warranties are provided), that licensees may convey the
120 | work under this License, and how to view a copy of this License. If
121 | the interface presents a list of user commands or options, such as a
122 | menu, a prominent item in the list meets this criterion.
123 |
124 | 1. Source Code.
125 |
126 | The "source code" for a work means the preferred form of the work
127 | for making modifications to it. "Object code" means any non-source
128 | form of a work.
129 |
130 | A "Standard Interface" means an interface that either is an official
131 | standard defined by a recognized standards body, or, in the case of
132 | interfaces specified for a particular programming language, one that
133 | is widely used among developers working in that language.
134 |
135 | The "System Libraries" of an executable work include anything, other
136 | than the work as a whole, that (a) is included in the normal form of
137 | packaging a Major Component, but which is not part of that Major
138 | Component, and (b) serves only to enable use of the work with that
139 | Major Component, or to implement a Standard Interface for which an
140 | implementation is available to the public in source code form. A
141 | "Major Component", in this context, means a major essential component
142 | (kernel, window system, and so on) of the specific operating system
143 | (if any) on which the executable work runs, or a compiler used to
144 | produce the work, or an object code interpreter used to run it.
145 |
146 | The "Corresponding Source" for a work in object code form means all
147 | the source code needed to generate, install, and (for an executable
148 | work) run the object code and to modify the work, including scripts to
149 | control those activities. However, it does not include the work's
150 | System Libraries, or general-purpose tools or generally available free
151 | programs which are used unmodified in performing those activities but
152 | which are not part of the work. For example, Corresponding Source
153 | includes interface definition files associated with source files for
154 | the work, and the source code for shared libraries and dynamically
155 | linked subprograms that the work is specifically designed to require,
156 | such as by intimate data communication or control flow between those
157 | subprograms and other parts of the work.
158 |
159 | The Corresponding Source need not include anything that users
160 | can regenerate automatically from other parts of the Corresponding
161 | Source.
162 |
163 | The Corresponding Source for a work in source code form is that
164 | same work.
165 |
166 | 2. Basic Permissions.
167 |
168 | All rights granted under this License are granted for the term of
169 | copyright on the Program, and are irrevocable provided the stated
170 | conditions are met. This License explicitly affirms your unlimited
171 | permission to run the unmodified Program. The output from running a
172 | covered work is covered by this License only if the output, given its
173 | content, constitutes a covered work. This License acknowledges your
174 | rights of fair use or other equivalent, as provided by copyright law.
175 |
176 | You may make, run and propagate covered works that you do not
177 | convey, without conditions so long as your license otherwise remains
178 | in force. You may convey covered works to others for the sole purpose
179 | of having them make modifications exclusively for you, or provide you
180 | with facilities for running those works, provided that you comply with
181 | the terms of this License in conveying all material for which you do
182 | not control copyright. Those thus making or running the covered works
183 | for you must do so exclusively on your behalf, under your direction
184 | and control, on terms that prohibit them from making any copies of
185 | your copyrighted material outside their relationship with you.
186 |
187 | Conveying under any other circumstances is permitted solely under
188 | the conditions stated below. Sublicensing is not allowed; section 10
189 | makes it unnecessary.
190 |
191 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
192 |
193 | No covered work shall be deemed part of an effective technological
194 | measure under any applicable law fulfilling obligations under article
195 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
196 | similar laws prohibiting or restricting circumvention of such
197 | measures.
198 |
199 | When you convey a covered work, you waive any legal power to forbid
200 | circumvention of technological measures to the extent such circumvention
201 | is effected by exercising rights under this License with respect to
202 | the covered work, and you disclaim any intention to limit operation or
203 | modification of the work as a means of enforcing, against the work's
204 | users, your or third parties' legal rights to forbid circumvention of
205 | technological measures.
206 |
207 | 4. Conveying Verbatim Copies.
208 |
209 | You may convey verbatim copies of the Program's source code as you
210 | receive it, in any medium, provided that you conspicuously and
211 | appropriately publish on each copy an appropriate copyright notice;
212 | keep intact all notices stating that this License and any
213 | non-permissive terms added in accord with section 7 apply to the code;
214 | keep intact all notices of the absence of any warranty; and give all
215 | recipients a copy of this License along with the Program.
216 |
217 | You may charge any price or no price for each copy that you convey,
218 | and you may offer support or warranty protection for a fee.
219 |
220 | 5. Conveying Modified Source Versions.
221 |
222 | You may convey a work based on the Program, or the modifications to
223 | produce it from the Program, in the form of source code under the
224 | terms of section 4, provided that you also meet all of these conditions:
225 |
226 | a) The work must carry prominent notices stating that you modified
227 | it, and giving a relevant date.
228 |
229 | b) The work must carry prominent notices stating that it is
230 | released under this License and any conditions added under section
231 | 7. This requirement modifies the requirement in section 4 to
232 | "keep intact all notices".
233 |
234 | c) You must license the entire work, as a whole, under this
235 | License to anyone who comes into possession of a copy. This
236 | License will therefore apply, along with any applicable section 7
237 | additional terms, to the whole of the work, and all its parts,
238 | regardless of how they are packaged. This License gives no
239 | permission to license the work in any other way, but it does not
240 | invalidate such permission if you have separately received it.
241 |
242 | d) If the work has interactive user interfaces, each must display
243 | Appropriate Legal Notices; however, if the Program has interactive
244 | interfaces that do not display Appropriate Legal Notices, your
245 | work need not make them do so.
246 |
247 | A compilation of a covered work with other separate and independent
248 | works, which are not by their nature extensions of the covered work,
249 | and which are not combined with it such as to form a larger program,
250 | in or on a volume of a storage or distribution medium, is called an
251 | "aggregate" if the compilation and its resulting copyright are not
252 | used to limit the access or legal rights of the compilation's users
253 | beyond what the individual works permit. Inclusion of a covered work
254 | in an aggregate does not cause this License to apply to the other
255 | parts of the aggregate.
256 |
257 | 6. Conveying Non-Source Forms.
258 |
259 | You may convey a covered work in object code form under the terms
260 | of sections 4 and 5, provided that you also convey the
261 | machine-readable Corresponding Source under the terms of this License,
262 | in one of these ways:
263 |
264 | a) Convey the object code in, or embodied in, a physical product
265 | (including a physical distribution medium), accompanied by the
266 | Corresponding Source fixed on a durable physical medium
267 | customarily used for software interchange.
268 |
269 | b) Convey the object code in, or embodied in, a physical product
270 | (including a physical distribution medium), accompanied by a
271 | written offer, valid for at least three years and valid for as
272 | long as you offer spare parts or customer support for that product
273 | model, to give anyone who possesses the object code either (1) a
274 | copy of the Corresponding Source for all the software in the
275 | product that is covered by this License, on a durable physical
276 | medium customarily used for software interchange, for a price no
277 | more than your reasonable cost of physically performing this
278 | conveying of source, or (2) access to copy the
279 | Corresponding Source from a network server at no charge.
280 |
281 | c) Convey individual copies of the object code with a copy of the
282 | written offer to provide the Corresponding Source. This
283 | alternative is allowed only occasionally and noncommercially, and
284 | only if you received the object code with such an offer, in accord
285 | with subsection 6b.
286 |
287 | d) Convey the object code by offering access from a designated
288 | place (gratis or for a charge), and offer equivalent access to the
289 | Corresponding Source in the same way through the same place at no
290 | further charge. You need not require recipients to copy the
291 | Corresponding Source along with the object code. If the place to
292 | copy the object code is a network server, the Corresponding Source
293 | may be on a different server (operated by you or a third party)
294 | that supports equivalent copying facilities, provided you maintain
295 | clear directions next to the object code saying where to find the
296 | Corresponding Source. Regardless of what server hosts the
297 | Corresponding Source, you remain obligated to ensure that it is
298 | available for as long as needed to satisfy these requirements.
299 |
300 | e) Convey the object code using peer-to-peer transmission, provided
301 | you inform other peers where the object code and Corresponding
302 | Source of the work are being offered to the general public at no
303 | charge under subsection 6d.
304 |
305 | A separable portion of the object code, whose source code is excluded
306 | from the Corresponding Source as a System Library, need not be
307 | included in conveying the object code work.
308 |
309 | A "User Product" is either (1) a "consumer product", which means any
310 | tangible personal property which is normally used for personal, family,
311 | or household purposes, or (2) anything designed or sold for incorporation
312 | into a dwelling. In determining whether a product is a consumer product,
313 | doubtful cases shall be resolved in favor of coverage. For a particular
314 | product received by a particular user, "normally used" refers to a
315 | typical or common use of that class of product, regardless of the status
316 | of the particular user or of the way in which the particular user
317 | actually uses, or expects or is expected to use, the product. A product
318 | is a consumer product regardless of whether the product has substantial
319 | commercial, industrial or non-consumer uses, unless such uses represent
320 | the only significant mode of use of the product.
321 |
322 | "Installation Information" for a User Product means any methods,
323 | procedures, authorization keys, or other information required to install
324 | and execute modified versions of a covered work in that User Product from
325 | a modified version of its Corresponding Source. The information must
326 | suffice to ensure that the continued functioning of the modified object
327 | code is in no case prevented or interfered with solely because
328 | modification has been made.
329 |
330 | If you convey an object code work under this section in, or with, or
331 | specifically for use in, a User Product, and the conveying occurs as
332 | part of a transaction in which the right of possession and use of the
333 | User Product is transferred to the recipient in perpetuity or for a
334 | fixed term (regardless of how the transaction is characterized), the
335 | Corresponding Source conveyed under this section must be accompanied
336 | by the Installation Information. But this requirement does not apply
337 | if neither you nor any third party retains the ability to install
338 | modified object code on the User Product (for example, the work has
339 | been installed in ROM).
340 |
341 | The requirement to provide Installation Information does not include a
342 | requirement to continue to provide support service, warranty, or updates
343 | for a work that has been modified or installed by the recipient, or for
344 | the User Product in which it has been modified or installed. Access to a
345 | network may be denied when the modification itself materially and
346 | adversely affects the operation of the network or violates the rules and
347 | protocols for communication across the network.
348 |
349 | Corresponding Source conveyed, and Installation Information provided,
350 | in accord with this section must be in a format that is publicly
351 | documented (and with an implementation available to the public in
352 | source code form), and must require no special password or key for
353 | unpacking, reading or copying.
354 |
355 | 7. Additional Terms.
356 |
357 | "Additional permissions" are terms that supplement the terms of this
358 | License by making exceptions from one or more of its conditions.
359 | Additional permissions that are applicable to the entire Program shall
360 | be treated as though they were included in this License, to the extent
361 | that they are valid under applicable law. If additional permissions
362 | apply only to part of the Program, that part may be used separately
363 | under those permissions, but the entire Program remains governed by
364 | this License without regard to the additional permissions.
365 |
366 | When you convey a copy of a covered work, you may at your option
367 | remove any additional permissions from that copy, or from any part of
368 | it. (Additional permissions may be written to require their own
369 | removal in certain cases when you modify the work.) You may place
370 | additional permissions on material, added by you to a covered work,
371 | for which you have or can give appropriate copyright permission.
372 |
373 | Notwithstanding any other provision of this License, for material you
374 | add to a covered work, you may (if authorized by the copyright holders of
375 | that material) supplement the terms of this License with terms:
376 |
377 | a) Disclaiming warranty or limiting liability differently from the
378 | terms of sections 15 and 16 of this License; or
379 |
380 | b) Requiring preservation of specified reasonable legal notices or
381 | author attributions in that material or in the Appropriate Legal
382 | Notices displayed by works containing it; or
383 |
384 | c) Prohibiting misrepresentation of the origin of that material, or
385 | requiring that modified versions of such material be marked in
386 | reasonable ways as different from the original version; or
387 |
388 | d) Limiting the use for publicity purposes of names of licensors or
389 | authors of the material; or
390 |
391 | e) Declining to grant rights under trademark law for use of some
392 | trade names, trademarks, or service marks; or
393 |
394 | f) Requiring indemnification of licensors and authors of that
395 | material by anyone who conveys the material (or modified versions of
396 | it) with contractual assumptions of liability to the recipient, for
397 | any liability that these contractual assumptions directly impose on
398 | those licensors and authors.
399 |
400 | All other non-permissive additional terms are considered "further
401 | restrictions" within the meaning of section 10. If the Program as you
402 | received it, or any part of it, contains a notice stating that it is
403 | governed by this License along with a term that is a further
404 | restriction, you may remove that term. If a license document contains
405 | a further restriction but permits relicensing or conveying under this
406 | License, you may add to a covered work material governed by the terms
407 | of that license document, provided that the further restriction does
408 | not survive such relicensing or conveying.
409 |
410 | If you add terms to a covered work in accord with this section, you
411 | must place, in the relevant source files, a statement of the
412 | additional terms that apply to those files, or a notice indicating
413 | where to find the applicable terms.
414 |
415 | Additional terms, permissive or non-permissive, may be stated in the
416 | form of a separately written license, or stated as exceptions;
417 | the above requirements apply either way.
418 |
419 | 8. Termination.
420 |
421 | You may not propagate or modify a covered work except as expressly
422 | provided under this License. Any attempt otherwise to propagate or
423 | modify it is void, and will automatically terminate your rights under
424 | this License (including any patent licenses granted under the third
425 | paragraph of section 11).
426 |
427 | However, if you cease all violation of this License, then your
428 | license from a particular copyright holder is reinstated (a)
429 | provisionally, unless and until the copyright holder explicitly and
430 | finally terminates your license, and (b) permanently, if the copyright
431 | holder fails to notify you of the violation by some reasonable means
432 | prior to 60 days after the cessation.
433 |
434 | Moreover, your license from a particular copyright holder is
435 | reinstated permanently if the copyright holder notifies you of the
436 | violation by some reasonable means, this is the first time you have
437 | received notice of violation of this License (for any work) from that
438 | copyright holder, and you cure the violation prior to 30 days after
439 | your receipt of the notice.
440 |
441 | Termination of your rights under this section does not terminate the
442 | licenses of parties who have received copies or rights from you under
443 | this License. If your rights have been terminated and not permanently
444 | reinstated, you do not qualify to receive new licenses for the same
445 | material under section 10.
446 |
447 | 9. Acceptance Not Required for Having Copies.
448 |
449 | You are not required to accept this License in order to receive or
450 | run a copy of the Program. Ancillary propagation of a covered work
451 | occurring solely as a consequence of using peer-to-peer transmission
452 | to receive a copy likewise does not require acceptance. However,
453 | nothing other than this License grants you permission to propagate or
454 | modify any covered work. These actions infringe copyright if you do
455 | not accept this License. Therefore, by modifying or propagating a
456 | covered work, you indicate your acceptance of this License to do so.
457 |
458 | 10. Automatic Licensing of Downstream Recipients.
459 |
460 | Each time you convey a covered work, the recipient automatically
461 | receives a license from the original licensors, to run, modify and
462 | propagate that work, subject to this License. You are not responsible
463 | for enforcing compliance by third parties with this License.
464 |
465 | An "entity transaction" is a transaction transferring control of an
466 | organization, or substantially all assets of one, or subdividing an
467 | organization, or merging organizations. If propagation of a covered
468 | work results from an entity transaction, each party to that
469 | transaction who receives a copy of the work also receives whatever
470 | licenses to the work the party's predecessor in interest had or could
471 | give under the previous paragraph, plus a right to possession of the
472 | Corresponding Source of the work from the predecessor in interest, if
473 | the predecessor has it or can get it with reasonable efforts.
474 |
475 | You may not impose any further restrictions on the exercise of the
476 | rights granted or affirmed under this License. For example, you may
477 | not impose a license fee, royalty, or other charge for exercise of
478 | rights granted under this License, and you may not initiate litigation
479 | (including a cross-claim or counterclaim in a lawsuit) alleging that
480 | any patent claim is infringed by making, using, selling, offering for
481 | sale, or importing the Program or any portion of it.
482 |
483 | 11. Patents.
484 |
485 | A "contributor" is a copyright holder who authorizes use under this
486 | License of the Program or a work on which the Program is based. The
487 | work thus licensed is called the contributor's "contributor version".
488 |
489 | A contributor's "essential patent claims" are all patent claims
490 | owned or controlled by the contributor, whether already acquired or
491 | hereafter acquired, that would be infringed by some manner, permitted
492 | by this License, of making, using, or selling its contributor version,
493 | but do not include claims that would be infringed only as a
494 | consequence of further modification of the contributor version. For
495 | purposes of this definition, "control" includes the right to grant
496 | patent sublicenses in a manner consistent with the requirements of
497 | this License.
498 |
499 | Each contributor grants you a non-exclusive, worldwide, royalty-free
500 | patent license under the contributor's essential patent claims, to
501 | make, use, sell, offer for sale, import and otherwise run, modify and
502 | propagate the contents of its contributor version.
503 |
504 | In the following three paragraphs, a "patent license" is any express
505 | agreement or commitment, however denominated, not to enforce a patent
506 | (such as an express permission to practice a patent or covenant not to
507 | sue for patent infringement). To "grant" such a patent license to a
508 | party means to make such an agreement or commitment not to enforce a
509 | patent against the party.
510 |
511 | If you convey a covered work, knowingly relying on a patent license,
512 | and the Corresponding Source of the work is not available for anyone
513 | to copy, free of charge and under the terms of this License, through a
514 | publicly available network server or other readily accessible means,
515 | then you must either (1) cause the Corresponding Source to be so
516 | available, or (2) arrange to deprive yourself of the benefit of the
517 | patent license for this particular work, or (3) arrange, in a manner
518 | consistent with the requirements of this License, to extend the patent
519 | license to downstream recipients. "Knowingly relying" means you have
520 | actual knowledge that, but for the patent license, your conveying the
521 | covered work in a country, or your recipient's use of the covered work
522 | in a country, would infringe one or more identifiable patents in that
523 | country that you have reason to believe are valid.
524 |
525 | If, pursuant to or in connection with a single transaction or
526 | arrangement, you convey, or propagate by procuring conveyance of, a
527 | covered work, and grant a patent license to some of the parties
528 | receiving the covered work authorizing them to use, propagate, modify
529 | or convey a specific copy of the covered work, then the patent license
530 | you grant is automatically extended to all recipients of the covered
531 | work and works based on it.
532 |
533 | A patent license is "discriminatory" if it does not include within
534 | the scope of its coverage, prohibits the exercise of, or is
535 | conditioned on the non-exercise of one or more of the rights that are
536 | specifically granted under this License. You may not convey a covered
537 | work if you are a party to an arrangement with a third party that is
538 | in the business of distributing software, under which you make payment
539 | to the third party based on the extent of your activity of conveying
540 | the work, and under which the third party grants, to any of the
541 | parties who would receive the covered work from you, a discriminatory
542 | patent license (a) in connection with copies of the covered work
543 | conveyed by you (or copies made from those copies), or (b) primarily
544 | for and in connection with specific products or compilations that
545 | contain the covered work, unless you entered into that arrangement,
546 | or that patent license was granted, prior to 28 March 2007.
547 |
548 | Nothing in this License shall be construed as excluding or limiting
549 | any implied license or other defenses to infringement that may
550 | otherwise be available to you under applicable patent law.
551 |
552 | 12. No Surrender of Others' Freedom.
553 |
554 | If conditions are imposed on you (whether by court order, agreement or
555 | otherwise) that contradict the conditions of this License, they do not
556 | excuse you from the conditions of this License. If you cannot convey a
557 | covered work so as to satisfy simultaneously your obligations under this
558 | License and any other pertinent obligations, then as a consequence you may
559 | not convey it at all. For example, if you agree to terms that obligate you
560 | to collect a royalty for further conveying from those to whom you convey
561 | the Program, the only way you could satisfy both those terms and this
562 | License would be to refrain entirely from conveying the Program.
563 |
564 | 13. Use with the GNU Affero General Public License.
565 |
566 | Notwithstanding any other provision of this License, you have
567 | permission to link or combine any covered work with a work licensed
568 | under version 3 of the GNU Affero General Public License into a single
569 | combined work, and to convey the resulting work. The terms of this
570 | License will continue to apply to the part which is the covered work,
571 | but the special requirements of the GNU Affero General Public License,
572 | section 13, concerning interaction through a network will apply to the
573 | combination as such.
574 |
575 | 14. Revised Versions of this License.
576 |
577 | The Free Software Foundation may publish revised and/or new versions of
578 | the GNU General Public License from time to time. Such new versions will
579 | be similar in spirit to the present version, but may differ in detail to
580 | address new problems or concerns.
581 |
582 | Each version is given a distinguishing version number. If the
583 | Program specifies that a certain numbered version of the GNU General
584 | Public License "or any later version" applies to it, you have the
585 | option of following the terms and conditions either of that numbered
586 | version or of any later version published by the Free Software
587 | Foundation. If the Program does not specify a version number of the
588 | GNU General Public License, you may choose any version ever published
589 | by the Free Software Foundation.
590 |
591 | If the Program specifies that a proxy can decide which future
592 | versions of the GNU General Public License can be used, that proxy's
593 | public statement of acceptance of a version permanently authorizes you
594 | to choose that version for the Program.
595 |
596 | Later license versions may give you additional or different
597 | permissions. However, no additional obligations are imposed on any
598 | author or copyright holder as a result of your choosing to follow a
599 | later version.
600 |
601 | 15. Disclaimer of Warranty.
602 |
603 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
604 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
605 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
606 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
607 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
608 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
609 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
610 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
611 |
612 | 16. Limitation of Liability.
613 |
614 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
615 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
616 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
617 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
618 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
619 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
620 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
621 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
622 | SUCH DAMAGES.
623 |
624 | 17. Interpretation of Sections 15 and 16.
625 |
626 | If the disclaimer of warranty and limitation of liability provided
627 | above cannot be given local legal effect according to their terms,
628 | reviewing courts shall apply local law that most closely approximates
629 | an absolute waiver of all civil liability in connection with the
630 | Program, unless a warranty or assumption of liability accompanies a
631 | copy of the Program in return for a fee.
632 |
633 | END OF TERMS AND CONDITIONS
634 |
635 | How to Apply These Terms to Your New Programs
636 |
637 | If you develop a new program, and you want it to be of the greatest
638 | possible use to the public, the best way to achieve this is to make it
639 | free software which everyone can redistribute and change under these terms.
640 |
641 | To do so, attach the following notices to the program. It is safest
642 | to attach them to the start of each source file to most effectively
643 | state the exclusion of warranty; and each file should have at least
644 | the "copyright" line and a pointer to where the full notice is found.
645 |
646 |
647 | Copyright (C)
648 |
649 | This program is free software: you can redistribute it and/or modify
650 | it under the terms of the GNU General Public License as published by
651 | the Free Software Foundation, either version 3 of the License, or
652 | (at your option) any later version.
653 |
654 | This program is distributed in the hope that it will be useful,
655 | but WITHOUT ANY WARRANTY; without even the implied warranty of
656 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
657 | GNU General Public License for more details.
658 |
659 | You should have received a copy of the GNU General Public License
660 | along with this program. If not, see .
661 |
662 | Also add information on how to contact you by electronic and paper mail.
663 |
664 | If the program does terminal interaction, make it output a short
665 | notice like this when it starts in an interactive mode:
666 |
667 | Copyright (C)
668 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
669 | This is free software, and you are welcome to redistribute it
670 | under certain conditions; type `show c' for details.
671 |
672 | The hypothetical commands `show w' and `show c' should show the appropriate
673 | parts of the General Public License. Of course, your program's commands
674 | might be different; for a GUI interface, you would use an "about box".
675 |
676 | You should also get your employer (if you work as a programmer) or school,
677 | if any, to sign a "copyright disclaimer" for the program, if necessary.
678 | For more information on this, and how to apply and follow the GNU GPL, see
679 | .
680 |
681 | The GNU General Public License does not permit incorporating your program
682 | into proprietary programs. If your program is a subroutine library, you
683 | may consider it more useful to permit linking proprietary applications with
684 | the library. If this is what you want to do, use the GNU Lesser General
685 | Public License instead of this License. But first, please read
686 | .
687 |
--------------------------------------------------------------------------------
/intelhexclass.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * INTEL HEX FILE CLASS MODULE
4 | *
5 | *******************************************************************************/
6 |
7 | /******************************************************************************/
8 | /*!
9 | * \file intelhexclass.cpp
10 | * \mainpage
11 | * \image html intelhexclass.png
12 | * \image latex intelhexclass.eps
13 | * \section intro Introduction
14 | * The Intel HEX File class module is designed to encode, decode and manipulate
15 | * the content of Intel HEX format files commonly generated by most toolchains
16 | * for embedded processors and microcontrollers.
17 | *
18 | * It uses standard C++ streams to decode files and store them in memory, and
19 | * encode data stored in memory back into an Intel HEX format file. Once the file
20 | * content is in memory, the content can then be manipulated using the available
21 | * API.
22 | *
23 | * With this class it is possible to create tools that can compare Intel HEX
24 | * files, fill empty space with desired values, splice two or more files
25 | * together to name a few possibilities.
26 | *
27 | * \section contactInfo Contact Information
28 | * For more information and the latest release, please visit this projects home
29 | * page at http://codinghead.github.com/Intel-HEX-Class
30 | * To participate in the project or for other enquiries, please contact Stuart
31 | * Cording at codinghead@gmail.com
32 | *
33 | * \section license Licensing Information
34 | * Copyright (c) 2012 Stuart Cording
35 | *
36 | * Permission is hereby granted, free of charge, to any person obtaining a copy
37 | * of this software and associated documentation files (the "Software"), to deal
38 | * in the Software without restriction, including without limitation the rights
39 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | * copies of the Software, and to permit persons to whom the Software is
41 | * furnished to do so, subject to the following conditions:
42 | *
43 | * The above copyright notice and this permission notice shall be included in all
44 | * copies or substantial portions of the Software.
45 | *
46 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 | * SOFTWARE.
53 | *
54 | * \section imageInfo Image Information
55 | * Image chosen for this project comes from 'Henkster'. Original image is from
56 | * http://www.sxc.hu/photo/504350 on stock.xchng.
57 | *
58 | * \author Stuart Cording aka CODINGHEAD
59 | *
60 | ********************************************************************************
61 | * \note
62 | * No notes to date (19th Jan 2012)
63 | *******************************************************************************/
64 |
65 | #include
66 | #include
67 | #include
68 | #ifdef _MSC_FULL_VER
69 | #include
70 | #else
71 | #include
72 | #endif
73 |
74 | #include "intelhexclass.h"
75 |
76 | using namespace std;
77 |
78 | /******************************************************************************/
79 | /*! Possible record types for Intel HEX file.
80 | *
81 | * List of all possible record types that can be found in an Intel HEX file.
82 | *******************************************************************************/
83 | enum intelhexRecordType {
84 | DATA_RECORD, // '00'
85 | END_OF_FILE_RECORD, // '01'
86 | EXTENDED_SEGMENT_ADDRESS, // '02'
87 | START_SEGMENT_ADDRESS, // '03'
88 | EXTENDED_LINEAR_ADDRESS, // '04'
89 | START_LINEAR_ADDRESS, // '05'
90 | NO_OF_RECORD_TYPES
91 | };
92 |
93 | /*******************************************************************************
94 | * Converts a 2 char string to its HEX value
95 | *******************************************************************************/
96 | unsigned char intelhex::stringToHex(string value)
97 | {
98 | unsigned char returnValue = 0;
99 | string::iterator valueIterator;
100 |
101 | if(value.length() == 2)
102 | {
103 | valueIterator = value.begin();
104 |
105 | for (int x=0; x < 2; x++)
106 | {
107 | /* Shift result variable 4 bits to the left */
108 | returnValue <<= 4;
109 |
110 | if (*valueIterator >= '0' && *valueIterator <= '9')
111 | {
112 | returnValue +=
113 | static_cast(*valueIterator - '0');
114 | }
115 | else if (*valueIterator >= 'A' && *valueIterator <= 'F')
116 | {
117 | returnValue +=
118 | static_cast(*valueIterator - 'A' + 10);
119 | }
120 | else if (*valueIterator >= 'a' && *valueIterator <= 'f')
121 | {
122 | returnValue +=
123 | static_cast(*valueIterator - 'a' + 10);
124 | }
125 | else
126 | {
127 | /* Error occured - non-HEX value found */
128 | string message;
129 |
130 | message = "Can't convert byte 0x" + value + " @ 0x" +
131 | ulToHexString(segmentBaseAddress) + " to hex.";
132 |
133 | addError(message);
134 |
135 | returnValue = 0;
136 | }
137 |
138 | /* Iterate to next char in the string */
139 | ++valueIterator;
140 | }
141 | }
142 | else
143 | {
144 | /* Error occured - more or less than two nibbles in the string */
145 | string message;
146 |
147 | message = value + " @ 0x" + ulToHexString(segmentBaseAddress) +
148 | " isn't an 8-bit value.";
149 |
150 | addError(message);
151 | }
152 |
153 | return returnValue;
154 | }
155 |
156 | /*******************************************************************************
157 | * Converts an unsigned long to a string in HEX format
158 | *******************************************************************************/
159 | string intelhex::ulToHexString(unsigned long value)
160 | {
161 | string returnString;
162 | char localString[50];
163 |
164 | returnString.erase();
165 |
166 | #ifdef _MSC_FULL_VER
167 | sprintf_s(localString, 49, "%08lX", value);
168 | #else
169 | snprintf(localString, 49, "%08lX", value);
170 | #endif
171 |
172 | returnString.insert(0, localString);
173 |
174 | return returnString;
175 | }
176 |
177 | /*******************************************************************************
178 | * Converts an unsigned long to a string in DEC format
179 | *******************************************************************************/
180 | string intelhex::ulToString(unsigned long value)
181 | {
182 | string returnString;
183 | char localString[50];
184 |
185 | returnString.erase();
186 |
187 | #ifdef _MSC_FULL_VER
188 | sprintf_s(localString, 49, "%lu", value);
189 | #else
190 | snprintf(localString, 49, "%lu", value);
191 | #endif
192 | returnString.insert(0, localString);
193 |
194 | return returnString;
195 | }
196 |
197 | /*******************************************************************************
198 | * Converts an unsigned char to a string in HEX format
199 | *******************************************************************************/
200 | string intelhex::ucToHexString(unsigned char value)
201 | {
202 | string returnString;
203 | char localString[50];
204 |
205 | returnString.erase();
206 |
207 | #ifdef _MSC_FULL_VER
208 | sprintf_s(localString, 49, "%02X", value);
209 | #else
210 | snprintf(localString, 49, "%02X", value);
211 | #endif
212 |
213 | returnString.insert(0, localString);
214 |
215 | return returnString;
216 | }
217 |
218 | /*******************************************************************************
219 | * Adds a warning to the list of warning messages
220 | *******************************************************************************/
221 | void intelhex::addWarning(string warningMessage)
222 | {
223 | string localMessage;
224 |
225 | /* Build the message and push the warning message onto the list */
226 | localMessage += ulToString(msgWarning.noOfWarnings + 1) + " Warning: "
227 | + warningMessage;
228 |
229 | msgWarning.ihWarnings.push_back(localMessage);
230 |
231 | /* Update the number of warning messages */
232 | msgWarning.noOfWarnings = msgWarning.ihWarnings.size();
233 | }
234 |
235 | /*******************************************************************************
236 | * Adds an error to the list of error messages
237 | *******************************************************************************/
238 | void intelhex::addError(string errorMessage)
239 | {
240 | string localMessage;
241 |
242 | /* Build the message and push the error message onto the list */
243 | localMessage += ulToString(msgError.noOfErrors + 1) + " Error: "
244 | + errorMessage;
245 |
246 | msgError.ihErrors.push_back(localMessage);
247 |
248 | /* Update the number of error messages */
249 | msgError.noOfErrors = msgError.ihErrors.size();
250 | }
251 |
252 | /*******************************************************************************
253 | * Decodes a data record read in from a file
254 | *******************************************************************************/
255 | void intelhex::decodeDataRecord(unsigned char recordLength,
256 | unsigned long loadOffset,
257 | string::const_iterator data)
258 | {
259 | /* Variable to store a byte of the record as a two char string */
260 | string sByteRead;
261 |
262 | /* Variable to store the byte of the record as an u.char */
263 | unsigned char byteRead;
264 |
265 | /* Calculate new SBA by clearing the low four bytes and then adding the */
266 | /* current loadOffset for this line of Intel HEX data */
267 | segmentBaseAddress &= ~(0xFFFFUL);
268 | segmentBaseAddress += loadOffset;
269 |
270 | for (unsigned char x = 0; x < recordLength; x ++)
271 | {
272 | sByteRead.erase();
273 |
274 | sByteRead = *data;
275 | data++;
276 | sByteRead += *data;
277 | data++;
278 |
279 | byteRead = stringToHex(sByteRead);
280 |
281 | ihReturn=ihContent.insert(
282 | pair(segmentBaseAddress, byteRead));
283 |
284 | if (ihReturn.second==false)
285 | {
286 | /* If this address already contains the byte we are trying to */
287 | /* write, this is only a warning */
288 | if (ihReturn.first->second == byteRead)
289 | {
290 | string message;
291 |
292 | message = "Location 0x" + ulToHexString(segmentBaseAddress) +
293 | " already contains data 0x" + sByteRead;
294 |
295 | addWarning(message);
296 | }
297 | /* Otherwise this is an error */
298 | else
299 | {
300 | string message;
301 |
302 | message = "Couldn't add 0x" + sByteRead + " @ 0x" +
303 | ulToHexString(segmentBaseAddress) +
304 | "; already contains 0x" +
305 | ucToHexString(ihReturn.first->second);
306 |
307 | addError(message);
308 | }
309 | }
310 |
311 | /* Increment the segment base address */
312 | ++segmentBaseAddress;
313 | }
314 | }
315 |
316 | /*******************************************************************************
317 | * Input Stream for Intel HEX File Decoding (friend function)
318 | *******************************************************************************/
319 | istream& operator>>(istream& dataIn, intelhex& ihLocal)
320 | {
321 | // Create a string to store lines of Intel Hex info
322 | string ihLine;
323 | /* Create a string to store a single byte of Intel HEX info */
324 | string ihByte;
325 | // Create an iterator for this variable
326 | string::iterator ihLineIterator;
327 | // Create a line counter
328 | unsigned long lineCounter = 0;
329 | // Variable to hold a single byte (two chars) of data
330 | unsigned char byteRead;
331 | // Variable to calculate the checksum for each line
332 | unsigned char intelHexChecksum;
333 | // Variable to hold the record length
334 | unsigned char recordLength;
335 | // Variable to hold the load offset
336 | unsigned long loadOffset;
337 | // Variables to hold the record type
338 | intelhexRecordType recordType;
339 |
340 | do
341 | {
342 | /* Clear the string before this next round */
343 | ihLine.erase();
344 |
345 | /* Clear the checksum before processing this line */
346 | intelHexChecksum = 0;
347 |
348 | /* Get a line of data */
349 | dataIn >> ihLine;
350 |
351 | /* If the line contained some data, process it */
352 | if (ihLine.length() > 0)
353 | {
354 | /* Increment line counter */
355 | lineCounter++;
356 |
357 | /* Set string iterator to start of string */
358 | ihLineIterator = ihLine.begin();
359 |
360 | /* Check that we have a ':' record mark at the beginning */
361 | if (*ihLineIterator != ':')
362 | {
363 | /* Add some warning code here */
364 | string message;
365 |
366 | message = "Line without record mark ':' found @ line " +
367 | ihLocal.ulToString(lineCounter);
368 |
369 | ihLocal.addWarning(message);
370 |
371 | /* If this is the first line, let's simply give up. Chances */
372 | /* are this is not an Intel HEX file at all */
373 | if (lineCounter == 1)
374 | {
375 | message = "Intel HEX File decode aborted; ':' missing in " \
376 | "first line.";
377 | ihLocal.addError(message);
378 |
379 | /* Erase ihLine content and break out of do...while loop */
380 | ihLine.erase();
381 | break;
382 | }
383 | }
384 | else
385 | {
386 | /* Remove the record mark from the string as we don't need it */
387 | /* anymore */
388 | ihLine.erase(ihLineIterator);
389 | }
390 |
391 | /* Run through the whole line to check the checksum */
392 | for (ihLineIterator = ihLine.begin();
393 | ihLineIterator != ihLine.end();
394 | /* Nothing - really! */ )
395 | {
396 | /* Convert the line in pair of chars (making a single byte) */
397 | /* into single bytes, and then add to the checksum variable. */
398 | /* By adding all the bytes in a line together *including* the */
399 | /* checksum byte, we should get a result of '0' at the end. */
400 | /* If not, there is a checksum error */
401 | ihByte.erase();
402 |
403 | ihByte = *ihLineIterator;
404 | ++ihLineIterator;
405 | /* Just in case there are an odd number of chars in the */
406 | /* just check we didn't reach the end of the string early */
407 | if (ihLineIterator != ihLine.end())
408 | {
409 | ihByte += *ihLineIterator;
410 | ++ihLineIterator;
411 |
412 | byteRead = ihLocal.stringToHex(ihByte);
413 |
414 | intelHexChecksum += byteRead;
415 | }
416 | else
417 | {
418 | string message;
419 |
420 | message = "Odd number of characters in line " +
421 | ihLocal.ulToString(lineCounter);
422 |
423 | ihLocal.addError(message);
424 | }
425 | }
426 |
427 | /* Make sure the checksum was ok */
428 | if (intelHexChecksum == 0)
429 | {
430 | /* Reset iterator back to beginning of the line so we can now */
431 | /* decode it */
432 | ihLineIterator = ihLine.begin();
433 |
434 | /* Clear all the variables associated with decoding a line of */
435 | /* Intel HEX code. */
436 | recordLength = 0;
437 | loadOffset = 0;
438 |
439 | /* Get the record length */
440 | ihByte.erase();
441 | ihByte = *ihLineIterator;
442 | ++ihLineIterator;
443 | ihByte += *ihLineIterator;
444 | ++ihLineIterator;
445 | recordLength = ihLocal.stringToHex(ihByte);
446 |
447 | /* Get the load offset (2 bytes) */
448 | ihByte.erase();
449 | ihByte = *ihLineIterator;
450 | ++ihLineIterator;
451 | ihByte += *ihLineIterator;
452 | ++ihLineIterator;
453 | loadOffset =
454 | static_cast(ihLocal.stringToHex(ihByte));
455 | loadOffset <<= 8;
456 | ihByte.erase();
457 | ihByte = *ihLineIterator;
458 | ++ihLineIterator;
459 | ihByte += *ihLineIterator;
460 | ++ihLineIterator;
461 | loadOffset +=
462 | static_cast(ihLocal.stringToHex(ihByte));
463 |
464 | /* Get the record type */
465 | ihByte.erase();
466 | ihByte = *ihLineIterator;
467 | ++ihLineIterator;
468 | ihByte += *ihLineIterator;
469 | ++ihLineIterator;
470 | recordType =
471 | static_cast(ihLocal.stringToHex(ihByte));
472 |
473 | /* Decode the INFO or DATA portion of the record */
474 | switch (recordType)
475 | {
476 | case DATA_RECORD:
477 | ihLocal.decodeDataRecord(recordLength, loadOffset,
478 | ihLineIterator);
479 | if (ihLocal.verbose == true)
480 | {
481 | cout << "Data Record begining @ 0x" <<
482 | ihLocal.ulToHexString(loadOffset) << endl;
483 | }
484 | break;
485 |
486 | case END_OF_FILE_RECORD:
487 | /* Check that the EOF record wasn't already found. If */
488 | /* it was, generate appropriate error */
489 | if (ihLocal.foundEof == false)
490 | {
491 | ihLocal.foundEof = true;
492 | }
493 | else
494 | {
495 | string message;
496 |
497 | message = "Additional End Of File record @ line " +
498 | ihLocal.ulToString(lineCounter) +
499 | " found.";
500 |
501 | ihLocal.addError(message);
502 | }
503 | /* Generate error if there were */
504 | if (ihLocal.verbose == true)
505 | {
506 | cout << "End of File" << endl;
507 | }
508 | break;
509 |
510 | case EXTENDED_SEGMENT_ADDRESS:
511 | /* Make sure we have 2 bytes of data */
512 | if (recordLength == 2)
513 | {
514 | /* Extract the two bytes of the ESA */
515 | unsigned long extSegAddress = 0;
516 |
517 | ihByte.erase();
518 | ihByte = *ihLineIterator;
519 | ++ihLineIterator;
520 | ihByte += *ihLineIterator;
521 | ++ihLineIterator;
522 | extSegAddress = static_cast
523 | (ihLocal.stringToHex(ihByte));
524 | extSegAddress <<= 8;
525 | ihByte.erase();
526 | ihByte = *ihLineIterator;
527 | ++ihLineIterator;
528 | ihByte += *ihLineIterator;
529 | ++ihLineIterator;
530 | extSegAddress += static_cast
531 | (ihLocal.stringToHex(ihByte));
532 |
533 | /* ESA is bits 4-19 of the segment base address */
534 | /* (SBA), so shift left 4 bits */
535 | extSegAddress <<= 4;
536 |
537 | /* Update the SBA */
538 | ihLocal.segmentBaseAddress = extSegAddress;
539 | }
540 | else
541 | {
542 | /* Note the error */
543 | string message;
544 |
545 | message = "Extended Segment Address @ line " +
546 | ihLocal.ulToString(lineCounter) +
547 | " not 2 bytes as required.";
548 |
549 | ihLocal.addError(message);
550 | }
551 | if (ihLocal.verbose == true)
552 | {
553 | cout << "Ext. Seg. Address found: 0x" <<
554 | ihLocal.ulToHexString(ihLocal.segmentBaseAddress)
555 | << endl;
556 | }
557 |
558 | break;
559 |
560 | case START_SEGMENT_ADDRESS:
561 | /* Make sure we have 4 bytes of data, and that no */
562 | /* Start Segment Address has been found to date */
563 | if (recordLength == 4 &&
564 | ihLocal.startSegmentAddress.exists == false)
565 | {
566 | /* Note that the Start Segment Address has been */
567 | /* found. */
568 | ihLocal.startSegmentAddress.exists = true;
569 | /* Clear the two registers, just in case */
570 | ihLocal.startSegmentAddress.csRegister = 0;
571 | ihLocal.startSegmentAddress.ipRegister = 0;
572 |
573 | ihByte.erase();
574 | ihByte = *ihLineIterator;
575 | ++ihLineIterator;
576 | ihByte += *ihLineIterator;
577 | ++ihLineIterator;
578 | ihLocal.startSegmentAddress.csRegister =
579 | static_cast
580 | (ihLocal.stringToHex(ihByte));
581 | ihLocal.startSegmentAddress.csRegister <<= 8;
582 | ihByte.erase();
583 | ihByte = *ihLineIterator;
584 | ++ihLineIterator;
585 | ihByte += *ihLineIterator;
586 | ++ihLineIterator;
587 | ihLocal.startSegmentAddress.csRegister +=
588 | static_cast
589 | (ihLocal.stringToHex(ihByte));
590 |
591 | ihByte.erase();
592 | ihByte = *ihLineIterator;
593 | ++ihLineIterator;
594 | ihByte += *ihLineIterator;
595 | ++ihLineIterator;
596 | ihLocal.startSegmentAddress.ipRegister =
597 | static_cast
598 | (ihLocal.stringToHex(ihByte));
599 | ihLocal.startSegmentAddress.ipRegister <<= 8;
600 | ihByte.erase();
601 | ihByte = *ihLineIterator;
602 | ++ihLineIterator;
603 | ihByte += *ihLineIterator;
604 | ++ihLineIterator;
605 | ihLocal.startSegmentAddress.ipRegister +=
606 | static_cast
607 | (ihLocal.stringToHex(ihByte));
608 | }
609 | /* Note an error if the start seg. address already */
610 | /* exists */
611 | else if (ihLocal.startSegmentAddress.exists == true)
612 | {
613 | string message;
614 |
615 | message = "Start Segment Address record appears again @ line " +
616 | ihLocal.ulToString(lineCounter) +
617 | "; repeated record ignored.";
618 |
619 | ihLocal.addError(message);
620 | }
621 | /* Note an error if the start lin. address already */
622 | /* exists as they should be mutually exclusive */
623 | if (ihLocal.startLinearAddress.exists == true)
624 | {
625 | string message;
626 |
627 | message = "Start Segment Address record found @ line " +
628 | ihLocal.ulToString(lineCounter) +
629 | " but Start Linear Address already exists.";
630 |
631 | ihLocal.addError(message);
632 | }
633 | /* Note an error if the record lenght is not 4 as */
634 | /* expected */
635 | if (recordLength != 4)
636 | {
637 | string message;
638 |
639 | message = "Start Segment Address @ line " +
640 | ihLocal.ulToString(lineCounter) +
641 | " not 4 bytes as required.";
642 |
643 | ihLocal.addError(message);
644 | }
645 | if (ihLocal.verbose == true)
646 | {
647 | cout << "Start Seg. Address - CS 0x" <<
648 | ihLocal.ulToHexString(ihLocal.startSegmentAddress.csRegister) <<
649 | " IP 0x" <<
650 | ihLocal.ulToHexString(ihLocal.startSegmentAddress.ipRegister)
651 | << endl;
652 | }
653 | break;
654 |
655 | case EXTENDED_LINEAR_ADDRESS:
656 | /* Make sure we have 2 bytes of data */
657 | if (recordLength == 2)
658 | {
659 | /* Extract the two bytes of the ELA */
660 | unsigned long extLinAddress = 0;
661 |
662 | ihByte.erase();
663 | ihByte = *ihLineIterator;
664 | ++ihLineIterator;
665 | ihByte += *ihLineIterator;
666 | ++ihLineIterator;
667 | extLinAddress = static_cast
668 | (ihLocal.stringToHex(ihByte));
669 | extLinAddress <<= 8;
670 | ihByte.erase();
671 | ihByte = *ihLineIterator;
672 | ++ihLineIterator;
673 | ihByte += *ihLineIterator;
674 | ++ihLineIterator;
675 | extLinAddress += static_cast
676 | (ihLocal.stringToHex(ihByte));
677 |
678 | /* ELA is bits 16-31 of the segment base address */
679 | /* (SBA), so shift left 16 bits */
680 | extLinAddress <<= 16;
681 |
682 | /* Update the SBA */
683 | ihLocal.segmentBaseAddress = extLinAddress;
684 | }
685 | else
686 | {
687 | /* Note the error */
688 | //cout << "Error in Ext. Lin. Address" << endl;
689 |
690 | string message;
691 |
692 | message = "Extended Linear Address @ line " +
693 | ihLocal.ulToString(lineCounter) +
694 | " not 2 bytes as required.";
695 |
696 | ihLocal.addError(message);
697 | }
698 | if (ihLocal.verbose == true)
699 | {
700 | cout << "Ext. Lin. Address 0x" <<
701 | ihLocal.ulToHexString(ihLocal.segmentBaseAddress)
702 | << endl;
703 | }
704 |
705 | break;
706 |
707 | case START_LINEAR_ADDRESS:
708 | /* Make sure we have 4 bytes of data */
709 | if (recordLength == 4 &&
710 | ihLocal.startLinearAddress.exists == false)
711 | {
712 | /* Note that the linear start address has been */
713 | /* found */
714 | ihLocal.startLinearAddress.exists = true;
715 |
716 | /* Clear the EIP register */
717 | ihLocal.startLinearAddress.eipRegister = 0;
718 |
719 | /* Extract the four bytes of the SLA */
720 | ihByte.erase();
721 | ihByte = *ihLineIterator;
722 | ++ihLineIterator;
723 | ihByte += *ihLineIterator;
724 | ++ihLineIterator;
725 | ihLocal.startLinearAddress.eipRegister =
726 | static_cast
727 | (ihLocal.stringToHex(ihByte));
728 | ihLocal.startLinearAddress.eipRegister <<= 8;
729 |
730 | ihByte.erase();
731 | ihByte = *ihLineIterator;
732 | ++ihLineIterator;
733 | ihByte += *ihLineIterator;
734 | ++ihLineIterator;
735 | ihLocal.startLinearAddress.eipRegister +=
736 | static_cast
737 | (ihLocal.stringToHex(ihByte));
738 | ihLocal.startLinearAddress.eipRegister <<= 8;
739 |
740 | ihByte.erase();
741 | ihByte = *ihLineIterator;
742 | ++ihLineIterator;
743 | ihByte += *ihLineIterator;
744 | ++ihLineIterator;
745 | ihLocal.startLinearAddress.eipRegister +=
746 | static_cast
747 | (ihLocal.stringToHex(ihByte));
748 | ihLocal.startLinearAddress.eipRegister <<= 8;
749 |
750 | ihByte.erase();
751 | ihByte = *ihLineIterator;
752 | ++ihLineIterator;
753 | ihByte += *ihLineIterator;
754 | ++ihLineIterator;
755 | ihLocal.startLinearAddress.eipRegister +=
756 | static_cast
757 | (ihLocal.stringToHex(ihByte));
758 |
759 | }
760 | /* Note an error if the start seg. address already */
761 | /* exists */
762 | else if (ihLocal.startLinearAddress.exists == true)
763 | {
764 | string message;
765 |
766 | message = "Start Linear Address record appears again @ line " +
767 | ihLocal.ulToString(lineCounter) +
768 | "; repeated record ignored.";
769 |
770 | ihLocal.addError(message);
771 | }
772 | /* Note an error if the start seg. address already */
773 | /* exists as they should be mutually exclusive */
774 | if (ihLocal.startSegmentAddress.exists == true)
775 | {
776 | string message;
777 |
778 | message = "Start Linear Address record found @ line " +
779 | ihLocal.ulToString(lineCounter) +
780 | " but Start Segment Address already exists.";
781 |
782 | ihLocal.addError(message);
783 | }
784 | /* Note an error if the record lenght is not 4 as */
785 | /* expected */
786 | if (recordLength != 4)
787 | {
788 | string message;
789 |
790 | message = "Start Linear Address @ line " +
791 | ihLocal.ulToString(lineCounter) +
792 | " not 4 bytes as required.";
793 |
794 | ihLocal.addError(message);
795 | }
796 | if (ihLocal.verbose == true)
797 | {
798 | cout << "Start Lin. Address - EIP 0x" <<
799 | ihLocal.ulToHexString(ihLocal.startLinearAddress.eipRegister)
800 | << endl;
801 | }
802 | break;
803 |
804 | default:
805 | /* Handle the error here */
806 | if (ihLocal.verbose == true)
807 | {
808 | cout << "Unknown Record @ line " <<
809 | ihLocal.ulToString(lineCounter) << endl;
810 | }
811 |
812 |
813 | string message;
814 |
815 | message = "Unknown Intel HEX record @ line " +
816 | ihLocal.ulToString(lineCounter);
817 |
818 | ihLocal.addError(message);
819 |
820 | break;
821 | }
822 | }
823 | else
824 | {
825 | /* Note that the checksum contained an error */
826 | string message;
827 |
828 | message = "Checksum error @ line " +
829 | ihLocal.ulToString(lineCounter) +
830 | "; calculated 0x" +
831 | ihLocal.ucToHexString(intelHexChecksum - byteRead) +
832 | " expected 0x" +
833 | ihLocal.ucToHexString(byteRead);
834 |
835 | ihLocal.addError(message);
836 | }
837 | }
838 | } while (ihLine.length() > 0);
839 |
840 | if (ihLocal.verbose == true)
841 | {
842 | cout << "Decoded " << lineCounter << " lines from file." << endl;
843 | }
844 |
845 | return(dataIn);
846 | }
847 |
848 | /*******************************************************************************
849 | * Output Stream for Intel HEX File Encoding (friend function)
850 | *******************************************************************************/
851 | ostream& operator<<(ostream& dataOut, intelhex& ihLocal)
852 | {
853 | /* Stores the address offset needed by the linear/segment address records */
854 | unsigned long addressOffset;
855 | /* Iterator into the ihContent - where the addresses & data are stored */
856 | map::iterator ihIterator;
857 | /* Holds string that represents next record to be written */
858 | string thisRecord;
859 | /* Checksum calculation variable */
860 | unsigned char checksum;
861 |
862 | thisRecord.clear();
863 |
864 | /* Check that there is some content to encode */
865 | if (ihLocal.ihContent.size() > 0)
866 | {
867 | /* Calculate the Linear/Segment address */
868 | ihIterator = ihLocal.ihContent.begin();
869 | addressOffset = (*ihIterator).first;
870 | checksum = 0;
871 |
872 | /* Construct the first record to define the segment base address */
873 | if (ihLocal.segmentAddressMode == false)
874 | {
875 | unsigned char dataByte;
876 |
877 | addressOffset >>= 16;
878 |
879 | thisRecord = ":02000004";
880 | checksum = 0x02 + 0x04;
881 |
882 | dataByte = static_cast(addressOffset & 0xFF);
883 | checksum += dataByte;
884 | thisRecord += ihLocal.ucToHexString(dataByte);
885 |
886 | dataByte = static_cast((addressOffset >> 8) & 0xFF);
887 | checksum += dataByte;
888 | thisRecord += ihLocal.ucToHexString(dataByte);
889 |
890 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
891 | }
892 | else
893 | {
894 | unsigned char dataByte;
895 |
896 | addressOffset >>= 4;
897 |
898 | thisRecord = ":02000002";
899 | checksum = 0x02 + 0x02;
900 |
901 | dataByte = static_cast(addressOffset & 0xFF);
902 | checksum += dataByte;
903 | thisRecord += ihLocal.ucToHexString(dataByte);
904 |
905 | dataByte = static_cast((addressOffset >> 8) & 0xFF);
906 | checksum += dataByte;
907 | thisRecord += ihLocal.ucToHexString(dataByte);
908 |
909 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
910 | }
911 |
912 | /* Output the record */
913 | dataOut << thisRecord << endl;
914 |
915 | /* Now loop through all the available data and insert into file */
916 | /* with maximum 16 bytes per line, and making sure to keep the */
917 | /* segment base address up to date */
918 | vector recordData;
919 | unsigned long previousAddress;
920 | unsigned long currentAddress;
921 | unsigned long loadOffset;
922 |
923 | while(ihIterator != ihLocal.ihContent.end())
924 | {
925 | /* Check to see if we need to start a new linear/segment section */
926 | loadOffset = (*ihIterator).first;
927 |
928 | /* If we are using the linear mode... */
929 | if (ihLocal.segmentAddressMode == false)
930 | {
931 | if ((loadOffset >> 16) != addressOffset)
932 | {
933 | unsigned char dataByte;
934 |
935 | thisRecord.clear();
936 | checksum = 0;
937 |
938 | addressOffset = loadOffset;
939 | addressOffset >>= 16;
940 |
941 | thisRecord = ":02000004";
942 | checksum = 0x02 + 0x04;
943 |
944 | dataByte = static_cast(addressOffset & 0xFF);
945 | checksum += dataByte;
946 | thisRecord += ihLocal.ucToHexString(dataByte);
947 |
948 | dataByte = static_cast((addressOffset >> 8) & 0xFF);
949 | checksum += dataByte;
950 | thisRecord += ihLocal.ucToHexString(dataByte);
951 |
952 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
953 |
954 | /* Output the record */
955 | dataOut << thisRecord << endl;
956 | }
957 | }
958 | /* ...otherwise assume segment mode */
959 | else
960 | {
961 | if ((loadOffset >> 4) != addressOffset)
962 | {
963 | unsigned char dataByte;
964 |
965 | thisRecord.clear();
966 | checksum = 0;
967 |
968 | addressOffset = loadOffset;
969 | addressOffset >>= 4;
970 |
971 | thisRecord = ":02000002";
972 | checksum = 0x02 + 0x02;
973 |
974 | dataByte = static_cast(addressOffset & 0xFF);
975 | checksum += dataByte;
976 | thisRecord += ihLocal.ucToHexString(dataByte);
977 |
978 | dataByte = static_cast((addressOffset >> 8) & 0xFF);
979 | checksum += dataByte;
980 | thisRecord += ihLocal.ucToHexString(dataByte);
981 |
982 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
983 |
984 | /* Output the record */
985 | dataOut << thisRecord << endl;
986 | }
987 | }
988 |
989 | /* Prepare for encoding next data record */
990 | thisRecord.clear();
991 | checksum = 0;
992 | recordData.clear();
993 |
994 | /* We need to check where the data actually starts, but only the */
995 | /* bottom 16-bits; the other bits are in the segment/linear */
996 | /* address record */
997 | loadOffset = (*ihIterator).first & 0xFFFF;
998 |
999 | /* Loop through and collect up to 16 bytes of data */
1000 | for (int x = 0; x < 16; x++)
1001 | {
1002 | currentAddress = (*ihIterator).first & 0xFFFF;
1003 |
1004 | recordData.push_back((*ihIterator).second);
1005 |
1006 | ihIterator++;
1007 |
1008 | /* Check that we haven't run out of data */
1009 | if (ihIterator == ihLocal.ihContent.end())
1010 | {
1011 | break;
1012 | }
1013 |
1014 | /* Check that the next address is consecutive */
1015 | previousAddress = currentAddress;
1016 | currentAddress = (*ihIterator).first & 0xFFFF;
1017 | if (currentAddress != (previousAddress + 1))
1018 | {
1019 | break;
1020 | }
1021 |
1022 | /* If we got here we have a consecutive address and can keep */
1023 | /* building up the data portion of the data record */
1024 | }
1025 |
1026 | /* Now we should have some data to encode; check first */
1027 | if (recordData.size() > 0)
1028 | {
1029 | vector::iterator itData;
1030 | unsigned char dataByte;
1031 |
1032 | /* Start building data record */
1033 | thisRecord = ":";
1034 |
1035 | /* Start with the RECLEN record length */
1036 | dataByte = static_cast(recordData.size());
1037 | thisRecord += ihLocal.ucToHexString(dataByte);
1038 | checksum += dataByte;
1039 |
1040 | /* Then the LOAD OFFSET */
1041 | dataByte = static_cast((loadOffset >> 8) & 0xFF);
1042 | thisRecord += ihLocal.ucToHexString(dataByte);
1043 | checksum += dataByte;
1044 | dataByte = static_cast(loadOffset & 0xFF);
1045 | thisRecord += ihLocal.ucToHexString(dataByte);
1046 | checksum += dataByte;
1047 |
1048 | /* Then the RECTYP record type (no need to add to checksum - */
1049 | /* value is zero '00' */
1050 | thisRecord += "00";
1051 |
1052 | /* Now we add the data */
1053 | for (itData = recordData.begin(); itData != recordData.end(); itData ++)
1054 | {
1055 | dataByte = (*itData);
1056 | checksum += dataByte;
1057 | thisRecord += ihLocal.ucToHexString(dataByte);
1058 | }
1059 |
1060 | /* Last bit - add the checksum */
1061 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
1062 |
1063 | /* Now write the record */
1064 | dataOut << thisRecord << endl;
1065 | }
1066 | }
1067 | }
1068 |
1069 | /* If there is a segment start address, output the data */
1070 | if (ihLocal.startSegmentAddress.exists == true)
1071 | {
1072 | unsigned char dataByte;
1073 |
1074 | thisRecord.clear();
1075 | checksum = 0;
1076 |
1077 | thisRecord = ":04000003";
1078 | checksum = 0x04 + 0x03;
1079 |
1080 | dataByte = static_cast((ihLocal.startSegmentAddress.csRegister >> 8) & 0xFF);
1081 | checksum += dataByte;
1082 | thisRecord += ihLocal.ucToHexString(dataByte);
1083 |
1084 | dataByte = static_cast(ihLocal.startSegmentAddress.csRegister & 0xFF);
1085 | checksum += dataByte;
1086 | thisRecord += ihLocal.ucToHexString(dataByte);
1087 |
1088 | dataByte = static_cast((ihLocal.startSegmentAddress.ipRegister >> 8) & 0xFF);
1089 | checksum += dataByte;
1090 | thisRecord += ihLocal.ucToHexString(dataByte);
1091 |
1092 | dataByte = static_cast(ihLocal.startSegmentAddress.ipRegister & 0xFF);
1093 | checksum += dataByte;
1094 | thisRecord += ihLocal.ucToHexString(dataByte);
1095 |
1096 |
1097 | /* Last bit - add the checksum */
1098 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
1099 |
1100 | /* Now write the record */
1101 | dataOut << thisRecord << endl;
1102 | }
1103 |
1104 | /* If there is a linear start address, output the data */
1105 | if (ihLocal.startLinearAddress.exists == true)
1106 | {
1107 | unsigned char dataByte;
1108 |
1109 | thisRecord.clear();
1110 | checksum = 0;
1111 |
1112 | thisRecord = ":04000005";
1113 | checksum = 0x04 + 0x05;
1114 |
1115 | dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 24) & 0xFF);
1116 | checksum += dataByte;
1117 | thisRecord += ihLocal.ucToHexString(dataByte);
1118 |
1119 | dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 16) & 0xFF);
1120 | checksum += dataByte;
1121 | thisRecord += ihLocal.ucToHexString(dataByte);
1122 |
1123 | dataByte = static_cast((ihLocal.startLinearAddress.eipRegister >> 8) & 0xFF);
1124 | checksum += dataByte;
1125 | thisRecord += ihLocal.ucToHexString(dataByte);
1126 |
1127 | dataByte = static_cast(ihLocal.startLinearAddress.eipRegister & 0xFF);
1128 | checksum += dataByte;
1129 | thisRecord += ihLocal.ucToHexString(dataByte);
1130 |
1131 |
1132 | /* Last bit - add the checksum */
1133 | thisRecord += ihLocal.ucToHexString(0x00 - (checksum & 0xFF));
1134 |
1135 | /* Now write the record */
1136 | dataOut << thisRecord << endl;
1137 | }
1138 |
1139 | /* Whatever happened, we can always output the EOF record */
1140 | dataOut << ":00000001FF" << endl;
1141 |
1142 | return (dataOut);
1143 | }
1144 |
1145 | /*******************************************************************************
1146 | *
1147 | * INTEL HEX FILE CLASS MODULE END
1148 | *
1149 | *******************************************************************************/
1150 |
--------------------------------------------------------------------------------