1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-14 21:23:52 +01:00
LibrePilot/ground/src/plugins/uploader/uploadergadgetwidget.cpp

301 lines
9.8 KiB
C++
Raw Normal View History

/**
******************************************************************************
*
* @file uploadergadgetwidget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup YModemUploader YModem Serial Uploader Plugin
* @{
* @brief The YModem protocol serial uploader plugin
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uploadergadgetwidget.h"
UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent)
{
m_config = new Ui_UploaderWidget();
m_config->setupUi(this);
currentStep = IAP_STATE_READY;
resetOnly=false;
//m_config->systemElements->addTab((QWidget*)new deviceWidget(),QString("Device"));
connect(m_config->haltButton, SIGNAL(clicked()), this, SLOT(goToBootloader()));
connect(m_config->resetButton, SIGNAL(clicked()), this, SLOT(systemReset()));
connect(m_config->bootButton, SIGNAL(clicked()), this, SLOT(systemBoot()));
}
/**
Tell the mainboard to go to bootloader:
- Send the relevant IAP commands
- setup callback for MoBo acknowledge
*/
void UploaderGadgetWidget::goToBootloader(UAVObject* callerObj, bool success)
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
UAVObject *fwIAP = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("FirmwareIAPObj")));
switch (currentStep) {
case IAP_STATE_READY:
// The board is running, send the 1st IAP Reset order:
fwIAP->getField("Command")->setValue("1122");
connect(fwIAP,SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(goToBootloader(UAVObject*, bool)));
currentStep = IAP_STATE_STEP_1;
fwIAP->updated();
clearLog();
log(QString("IAP Step 1"));
break;
case IAP_STATE_STEP_1:
if (!success) {
log(QString("Oops, failure step 1"));
log("Reset did NOT happen");
currentStep == IAP_STATE_READY;
disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(goToBootloader(UAVObject*, bool)));
break;
}
delay::msleep(600);
fwIAP->getField("Command")->setValue("2233");
currentStep = IAP_STATE_STEP_2;
fwIAP->updated();
log(QString("IAP Step 2"));
break;
case IAP_STATE_STEP_2:
if (!success) {
log(QString("Oops, failure step 2"));
log("Reset did NOT happen");
currentStep == IAP_STATE_READY;
disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(goToBootloader(UAVObject*, bool)));
break;
}
delay::msleep(600);
fwIAP->getField("Command")->setValue("3344");
currentStep = IAP_STEP_RESET;
fwIAP->updated();
log(QString("IAP Step 3"));
break;
case IAP_STEP_RESET: {
currentStep = IAP_STATE_READY;
if (success) {
log("Oops, unexpected success step 3");
log("Reset did NOT happen");
disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(goToBootloader(UAVObject*, bool)));
break;
}
// The board is now reset: we have to disconnect telemetry
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
cm->disconnectDevice();
log("Board Reset");
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject*,bool)),this,SLOT(goToBootloader(UAVObject*, bool)));
if (resetOnly) {
resetOnly=false;
break;
}
// stop the polling thread: otherwise it will mess up DFU
RawHIDConnection *cnx = pm->getObject<RawHIDConnection>();
cnx->suspendPolling();
// Tell the mainboard to get into bootloader state:
log("Going into Bootloader mode...");
OP_DFU dfu(true);
dfu.AbortOperation();
if(!dfu.enterDFU(0))
{
log("Could not enter DFU mode.");
return;
}
m_config->boardStatus->setText("Bootloader");
currentStep = IAP_STATE_BOOTLOADER;
OP_DFU::Status ret=dfu.StatusRequest();
dfu.findDevices();
log(QString("Found ") + QString::number(dfu.numberOfDevices) + QString(" device(s)."));
// Delete all previous tabs:
for (int i=0; i< m_config->systemElements->count(); i++) {
QWidget *qw = m_config->systemElements->widget(i);
m_config->systemElements->removeTab(i);
delete qw;
}
for(int i=0;i<dfu.numberOfDevices;i++) {
deviceWidget* dw = new deviceWidget(this);
dw->setDeviceID(i);
dw->setDfu(&dfu);
dw->populate();
m_config->systemElements->addTab(dw, QString("Device") + QString::number(i));
}
m_config->haltButton->setEnabled(false);
m_config->resetButton->setEnabled(false);
m_config->bootButton->setEnabled(true);
}
}
}
/**
Tell the mainboard to reset:
- Send the relevant IAP commands
- setup callback for MoBo acknowledge
*/
void UploaderGadgetWidget::systemReset()
{
resetOnly = true;
m_config->textBrowser->clear();
log("Board Reset initiated.");
goToBootloader();
}
/**
Tells the system to boot (from Bootloader state)
*/
void UploaderGadgetWidget::systemBoot()
{
if (currentStep == IAP_STATE_BOOTLOADER) {
clearLog();
OP_DFU dfu(true);
dfu.AbortOperation();
if(!dfu.enterDFU(0))
{
log("Could not enter DFU mode.");
return;
}
log("Booting system...");
dfu.JumpToApp();
currentStep = IAP_STATE_READY;
// stop the polling thread: otherwise it will mess up DFU
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
RawHIDConnection *cnx = pm->getObject<RawHIDConnection>();
cnx->resumePolling();
m_config->bootButton->setEnabled(false);
m_config->haltButton->setEnabled(true);
m_config->resetButton->setEnabled(true);
m_config->boardStatus->setText("Running");
} else {
log("Not in bootloader mode!");
}
}
/**
Update log entry
*/
void UploaderGadgetWidget::log(QString str)
{
m_config->textBrowser->append(str);
}
void UploaderGadgetWidget::clearLog()
{
m_config->textBrowser->clear();
}
//user pressed send, send file using a new thread with qymodem library
void UploaderGadgetWidget::send()
{
Ymodem->SendFileT(openFileNameLE->text());
}
//destructor !!?! do I need to delete something else?
UploaderGadgetWidget::~UploaderGadgetWidget()
{
delete Port;
delete Ymodem;
}
//from load configuration, creates a new qymodemsend class with the the port
/**
Cteates a new qymodemsend class.
@param port The serial port to use.
*/
void UploaderGadgetWidget::setPort(QextSerialPort* port)
{
Port=port;
Ymodem=new QymodemSend(*Port);
//only now can we connect this signals
//signals errors
connect(Ymodem,SIGNAL(Error(QString,int))
,this,SLOT(error(QString,int)));
//signals new information
connect(Ymodem,SIGNAL(Information(QString,int)),
this,SLOT(info(QString,int)));
//signals new percentage value
connect(Ymodem,SIGNAL(Percent(int)),
this,SLOT(updatePercSlot(int)));
}
/**
Updates progress bar value.
@param i New percentage value.
*/
void UploaderGadgetWidget::updatePercSlot(int i)
{
progressBar->setValue(i);
}
/**
Opens an open file dialog.
*/
void UploaderGadgetWidget::setOpenFileName()
{
QFileDialog::Options options;
QString selectedFilter;
QString fileName = QFileDialog::getOpenFileName(this,
tr("QFileDialog::getOpenFileName()"),
openFileNameLE->text(),
tr("All Files (*);;Text Files (*.bin)"),
&selectedFilter,
options);
if (!fileName.isEmpty()) openFileNameLE->setText(fileName);
}
/**
Shows a message box with an error string.
@param errorString The error string to display.
@param errorNumber Not used
*/
void UploaderGadgetWidget::error(QString errorString, int errorNumber)
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(errorString);
msgBox.exec();
status->setText(errorString);
}
/**
Shows a message box with an information string.
@param infoString The information string to display.
@param infoNumber Not used
*/
void UploaderGadgetWidget::info(QString infoString, int infoNumber)
{
status->setText(infoString);
}