You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1310 lines
47 KiB

/*
* Remote Laboratory FPGA Viewer Part
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (c) 2012-2019 Timothy Pearson
* Raptor Engineering
* http://www.raptorengineeringinc.com
*/
#include "define.h"
#include "part.h"
#include <tdeaboutdata.h> //::createAboutData()
#include <tdeaction.h>
#include <tdelocale.h>
#include <tdemessagebox.h> //::start()
#include <tdeparts/genericfactory.h>
#include <tdemdimainfrm.h>
#include <kstatusbar.h>
#include <kstdaction.h>
#include <knuminput.h>
#include <kmdcodec.h>
#include <kurlrequester.h>
#include <tqfile.h> //encodeName()
#include <tqtimer.h> //postInit() hack
#include <tqvbox.h>
#include <tqsocket.h>
#include <tqmutex.h>
#include <tqeventloop.h>
#include <tqapplication.h>
#include <tqgroupbox.h>
#include <tqcheckbox.h>
#include <tqpushbutton.h>
#include <tqprogressbar.h>
#include <unistd.h> //access()
#include <stdint.h>
#include <math.h>
#include <tqpainter.h>
#include "tracewidget.h"
#include "floatspinbox.h"
#include "layout.h"
#define SERVER_TIMEOUT_MS 20000
#define FPGA_COMM_TIMEOUT_MS 2000
#define FPGA_DATA_PROCESSING_TIMEOUT_MS 19000
FPGALed::FPGALed(TQWidget *parent, const char *name)
: KLed(parent, name), m_clickable(true)
{
connect(this, SIGNAL(clicked()), this, SLOT(toggle()));
setColor(green);
setOffColor(TQApplication::palette(this).active().base().dark(200));
}
void FPGALed::setClickable(bool clickable) {
if ((!clickable) && (m_clickable)) {
disconnect(this, SIGNAL(clicked()), this, SLOT(toggle()));
}
else if ((clickable) && (!m_clickable)) {
connect(this, SIGNAL(clicked()), this, SLOT(toggle()));
}
m_clickable = clickable;
}
void FPGALed::mouseReleaseEvent(TQMouseEvent *e) {
if (e->button() == TQMouseEvent::LeftButton) {
emit(clicked());
}
}
FPGAPushButton::FPGAPushButton(TQWidget *parent, const char *name)
: KLed(parent, name), mouseDown(false)
{
off();
setColor(green);
setOffColor(TQApplication::palette(this).active().base().dark(200));
}
void FPGAPushButton::mousePressEvent(TQMouseEvent *e) {
if (e->button() == TQMouseEvent::LeftButton) {
on();
mouseDown = true;
emit(buttonPressed());
emit(changed());
}
}
void FPGAPushButton::mouseReleaseEvent(TQMouseEvent *e) {
if (e->button() == TQMouseEvent::LeftButton) {
off();
mouseDown = false;
emit(buttonReleased());
emit(changed());
}
}
void FPGAPushButton::enterEvent(TQEvent *e) {
Q_UNUSED(e);
if (mouseDown) {
on();
emit(buttonPressed());
emit(changed());
}
}
void FPGAPushButton::leaveEvent(TQEvent *e) {
Q_UNUSED(e);
if (mouseDown) {
off();
emit(buttonReleased());
emit(changed());
}
}
ImageViewerWindow::ImageViewerWindow(TQString caption, TQWidget *parent, const char *name)
: KMdiChildView(caption, parent, name)
{
TQGridLayout* layout = new TQGridLayout(this);
m_label = new TQLabel(this);
m_label->setScaledContents(true);
layout->addWidget(m_label, 0, 0);
}
ImageViewerWindow::~ImageViewerWindow() {
//
}
void ImageViewerWindow::resizeEvent(TQResizeEvent *) {
//
}
void ImageViewerWindow::setPixmap(TQPixmap pixmap) {
m_label->setPixmap(pixmap);
}
namespace RemoteLab {
typedef KParts::GenericFactory<RemoteLab::FPGAViewPart> Factory;
#define CLIENT_LIBRARY "libremotelab_fpgaviewer"
K_EXPORT_COMPONENT_FACTORY(libremotelab_fpgaviewer, RemoteLab::Factory)
#define LED_BASE_SIZE 20
#define LED_SIZE LED_BASE_SIZE,LED_BASE_SIZE
FPGAViewPart::FPGAViewPart(TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const TQStringList&)
: RemoteInstrumentPart( parent, name ), m_base(NULL), m_interfaceMode(BasicInterfaceMode),
m_commHandlerState(0), m_commHandlerMode(0), m_commHandlerNextState(0), m_commHandlerNextMode(0), m_connectionActiveAndValid(false), m_tickerState(0), m_remoteInputModeEnabled(false), m_4bitInputValue(0), m_4bitOutputValue(0),
m_8bitInputValue(0), m_8bitOutputValue(0), m_16bitInputValue(0), m_16bitOutputValue(0), m_7segDigit3OutputValue(0xff),
m_7segDigit2OutputValue(0xff), m_7segDigit1OutputValue(0xff), m_7segDigit0OutputValue(0xff), m_sendingUserLogicReset(false),
m_batchOutputFile(NULL), m_dataOutputFile(NULL), m_dataMemorySize(16384), m_dataMemorySizePrev(0),
m_dataMemoryImageWidth(128), m_dataMemoryImageHeight(128),
m_inputImageViewer(NULL), m_outputImageViewer(NULL)
{
// Initialize important base class variables
m_clientLibraryName = CLIENT_LIBRARY;
// Initialize mutex
m_connectionMutex = new TQMutex(false);
// Initialize kpart
setInstance(Factory::instance());
setWidget(new TQVBox(parentWidget, widgetName));
// Create timers
m_updateTimer = new TQTimer(this);
m_timeoutTimer = new TQTimer(this);
m_connectionTimer = new TQTimer(this);
connect(m_connectionTimer, SIGNAL(timeout()), this, SLOT(finishConnectingToServer()));
// Create widgets
m_base = new FPGAViewBase(widget());
// Load configuration
m_config = new KSimpleConfig("ulab_client_part_fpgaviewer.conf", false);
m_config->setGroup("UI");
m_interfaceMode = (RemoteLab::FPGAViewPart::InterfaceMode)(m_config->readNumEntry("interfaceMode", BasicInterfaceMode));
m_base->batchTestInputFile->setURL(m_config->readPathEntry("batchTestInputFile", ""));
m_base->batchTestOutputFile->setURL(m_config->readPathEntry("batchTestOutputFile", ""));
m_base->batchTest16BitCheckBox->setChecked(m_config->readBoolEntry("batchUsing16Bit", false));
m_base->dataProcessingInputFile->setURL(m_config->readPathEntry("dataProcessingInputFile", ""));
m_base->dataProcessingOutputFile->setURL(m_config->readPathEntry("dataProcessingOutputFile", ""));
// Create menu actions
// Submenus
TDEActionCollection *const ac = actionCollection();
m_modeSubMenu = new TDEActionMenu(i18n("Mode"), ac, "mode_submenu");
m_menuActionList.append(m_modeSubMenu);
// Menu items
m_modeBasicEnabled = new TDEToggleAction(i18n("Basic"), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(switchToBasicMode()), ac, "mode_basic_enabled");
m_modeSubMenu->insert(m_modeBasicEnabled);
m_modeIntermediateEnabled = new TDEToggleAction(i18n("Intermediate"), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(switchToIntermediateMode()), ac, "mode_intermediate_enabled");
m_modeSubMenu->insert(m_modeIntermediateEnabled);
m_modeAdvancedEnabled = new TDEToggleAction(i18n("Advanced"), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(switchToAdvancedMode()), ac, "mode_advanced_enabled");
m_modeSubMenu->insert(m_modeAdvancedEnabled);
// Initialize widgets
m_base->group4BitInputLED3->setFixedSize(LED_SIZE);
m_base->group4BitInputLED2->setFixedSize(LED_SIZE);
m_base->group4BitInputLED1->setFixedSize(LED_SIZE);
m_base->group4BitInputLED0->setFixedSize(LED_SIZE);
m_base->group4BitOutputLED3->setFixedSize(LED_SIZE);
m_base->group4BitOutputLED2->setFixedSize(LED_SIZE);
m_base->group4BitOutputLED1->setFixedSize(LED_SIZE);
m_base->group4BitOutputLED0->setFixedSize(LED_SIZE);
m_base->group8BitInputLED7->setFixedSize(LED_SIZE);
m_base->group8BitInputLED6->setFixedSize(LED_SIZE);
m_base->group8BitInputLED5->setFixedSize(LED_SIZE);
m_base->group8BitInputLED4->setFixedSize(LED_SIZE);
m_base->group8BitInputLED3->setFixedSize(LED_SIZE);
m_base->group8BitInputLED2->setFixedSize(LED_SIZE);
m_base->group8BitInputLED1->setFixedSize(LED_SIZE);
m_base->group8BitInputLED0->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED7->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED6->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED5->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED4->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED3->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED2->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED1->setFixedSize(LED_SIZE);
m_base->group8BitOutputLED0->setFixedSize(LED_SIZE);
m_base->group4BitInputLED3->setState(KLed::Off);
m_base->group4BitInputLED2->setState(KLed::Off);
m_base->group4BitInputLED1->setState(KLed::Off);
m_base->group4BitInputLED0->setState(KLed::Off);
m_base->group4BitOutputLED3->setState(KLed::Off);
m_base->group4BitOutputLED2->setState(KLed::Off);
m_base->group4BitOutputLED1->setState(KLed::Off);
m_base->group4BitOutputLED0->setState(KLed::Off);
m_base->group8BitInputLED7->setState(KLed::Off);
m_base->group8BitInputLED6->setState(KLed::Off);
m_base->group8BitInputLED5->setState(KLed::Off);
m_base->group8BitInputLED4->setState(KLed::Off);
m_base->group8BitInputLED3->setState(KLed::Off);
m_base->group8BitInputLED2->setState(KLed::Off);
m_base->group8BitInputLED1->setState(KLed::Off);
m_base->group8BitInputLED0->setState(KLed::Off);
m_base->group8BitOutputLED7->setState(KLed::Off);
m_base->group8BitOutputLED6->setState(KLed::Off);
m_base->group8BitOutputLED5->setState(KLed::Off);
m_base->group8BitOutputLED4->setState(KLed::Off);
m_base->group8BitOutputLED3->setState(KLed::Off);
m_base->group8BitOutputLED2->setState(KLed::Off);
m_base->group8BitOutputLED1->setState(KLed::Off);
m_base->group8BitOutputLED0->setState(KLed::Off);
m_base->group4BitOutputLED3->setClickable(false);
m_base->group4BitOutputLED2->setClickable(false);
m_base->group4BitOutputLED1->setClickable(false);
m_base->group4BitOutputLED0->setClickable(false);
m_base->group8BitOutputLED7->setClickable(false);
m_base->group8BitOutputLED6->setClickable(false);
m_base->group8BitOutputLED5->setClickable(false);
m_base->group8BitOutputLED4->setClickable(false);
m_base->group8BitOutputLED3->setClickable(false);
m_base->group8BitOutputLED2->setClickable(false);
m_base->group8BitOutputLED1->setClickable(false);
m_base->group8BitOutputLED0->setClickable(false);
#if 0
TQFontMetrics group8BitTextMetrics(m_base->group8BitOutputValueText->font());
m_base->group8BitInputValueText->setFixedSize(group8BitTextMetrics.width("0000"), group8BitTextMetrics.height());
m_base->group8BitOutputValueText->setFixedSize(group8BitTextMetrics.width("0000"), group8BitTextMetrics.height());
#endif
connect(m_base->group4BitInputLED3, SIGNAL(changed()), this, SLOT(process4BitInputChanges()));
connect(m_base->group4BitInputLED2, SIGNAL(changed()), this, SLOT(process4BitInputChanges()));
connect(m_base->group4BitInputLED1, SIGNAL(changed()), this, SLOT(process4BitInputChanges()));
connect(m_base->group4BitInputLED0, SIGNAL(changed()), this, SLOT(process4BitInputChanges()));
connect(m_base->group8BitInputLED7, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED6, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED5, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED4, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED3, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED2, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED1, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group8BitInputLED0, SIGNAL(clicked()), this, SLOT(process8BitInputChanges()));
connect(m_base->group16BitInputValue, SIGNAL(valueChanged(int)), this, SLOT(process16BitInputChanges()));
m_base->LEDOutputDisplayDigit0->setBackgroundColor(TQt::black);
m_base->LEDOutputDisplayDigit1->setBackgroundColor(TQt::black);
m_base->LEDOutputDisplayDigit2->setBackgroundColor(TQt::black);
m_base->LEDOutputDisplayDigit3->setBackgroundColor(TQt::black);
m_base->LEDOutputDisplayDigit0->setPaletteForegroundColor(TQColor(0, 255, 64));
m_base->LEDOutputDisplayDigit1->setPaletteForegroundColor(TQColor(0, 255, 64));
m_base->LEDOutputDisplayDigit2->setPaletteForegroundColor(TQColor(0, 255, 64));
m_base->LEDOutputDisplayDigit3->setPaletteForegroundColor(TQColor(0, 255, 64));
// The LED display can work one of two ways
#if 0
// Separated segments
m_base->LEDOutputDisplayDigit0->setFrameStyle(TQFrame::Box | TQFrame::Raised);
m_base->LEDOutputDisplayDigit1->setFrameStyle(TQFrame::Box | TQFrame::Raised);
m_base->LEDOutputDisplayDigit2->setFrameStyle(TQFrame::Box | TQFrame::Raised);
m_base->LEDOutputDisplayDigit3->setFrameStyle(TQFrame::Box | TQFrame::Raised);
m_base->frameLEDDisplay->setFrameStyle(TQFrame::NoFrame);
#else
// Combined segments
m_base->frameLEDDisplay->setBackgroundColor(TQt::black);
m_base->LEDOutputDisplayDigit0->setFrameStyle(TQFrame::NoFrame);
m_base->LEDOutputDisplayDigit1->setFrameStyle(TQFrame::NoFrame);
m_base->LEDOutputDisplayDigit2->setFrameStyle(TQFrame::NoFrame);
m_base->LEDOutputDisplayDigit3->setFrameStyle(TQFrame::NoFrame);
m_base->frameLEDDisplay->setFrameStyle(TQFrame::Box | TQFrame::Raised);
#endif
m_base->frameLCDDisplay->setBackgroundColor(TQColor(192, 192, 192));
m_base->LCDOutputLabel->setBackgroundColor(TQColor(192, 192, 192));
m_base->LCDOutputLabel->setPaletteForegroundColor(TQColor(0, 0, 0));
TQFontMetrics lcdmetrics(m_base->LCDOutputLabel->font());
int lcdwidth = lcdmetrics.width("0000000000000000");
int lcdheight = lcdmetrics.height()*2;
m_base->LCDOutputLabel->setFixedSize(lcdwidth, lcdheight);
m_base->frameLCDDisplay->setFrameStyle(TQFrame::Box | TQFrame::Raised);
connect(m_base->groupGlobalControlResetButton, SIGNAL(clicked()), this, SLOT(groupGlobalControlResetButtonClicked()));
connect(m_base->batchTestRunButton, SIGNAL(clicked()), this, SLOT(batchTestRunButtonClicked()));
connect(m_base->dataProcessingRunButton, SIGNAL(clicked()), this, SLOT(dataProcessingRunButtonClicked()));
connect(m_base->batchTestInputFile, SIGNAL(textChanged(const TQString &)), this, SLOT(processLockouts()));
connect(m_base->batchTestOutputFile, SIGNAL(textChanged(const TQString &)), this, SLOT(processLockouts()));
connect(m_base->dataProcessingInputFile, SIGNAL(textChanged(const TQString &)), this, SLOT(processLockouts()));
connect(m_base->dataProcessingOutputFile, SIGNAL(textChanged(const TQString &)), this, SLOT(processLockouts()));
TQTimer::singleShot(0, this, TQT_SLOT(postInit()));
}
FPGAViewPart::~FPGAViewPart() {
// Save field state for restoration on next load
m_config->setGroup("UI");
m_config->writeEntry("interfaceMode", m_interfaceMode);
m_config->writeEntry("batchTestInputFile", m_base->batchTestInputFile->url());
m_config->writeEntry("batchTestOutputFile", m_base->batchTestOutputFile->url());
m_config->writeEntry("batchUsing16Bit", m_base->batchTest16BitCheckBox->isChecked());
m_config->writeEntry("dataProcessingInputFile", m_base->dataProcessingInputFile->url());
m_config->writeEntry("dataProcessingOutputFile", m_base->dataProcessingOutputFile->url());
m_config->sync();
delete m_config;
// Close any active image display windows
m_interfaceMode = BasicInterfaceMode;
if (m_inputImageViewer) {
mdiMainForm()->closeWindow(m_inputImageViewer);
m_inputImageViewer = NULL;
}
if (m_outputImageViewer) {
mdiMainForm()->closeWindow(m_outputImageViewer);
m_outputImageViewer = NULL;
}
if (m_connectionMutex->locked()) {
printf("[WARNING] Exiting when data transfer still in progress!\n\r"); fflush(stdout);
}
disconnectFromServer();
delete m_connectionMutex;
}
void FPGAViewPart::processAllGraphicsUpdates() {
// This is an expensive operation
// Use it sparingly!
process4BitInputChanges();
process4BitOutputChanges();
process8BitInputChanges();
process8BitOutputChanges();
process16BitInputChanges();
process16BitOutputChanges();
processLCDOutputChanges();
process7SegmentLEDOutputChanges();
processLockouts();
}
void FPGAViewPart::process4BitInputChanges() {
// Read LED status into m_4bitInputValue
m_4bitInputValue = 0;
if (m_base->group4BitInputLED3->state() == KLed::On) m_4bitInputValue |= 0x08;
if (m_base->group4BitInputLED2->state() == KLed::On) m_4bitInputValue |= 0x04;
if (m_base->group4BitInputLED1->state() == KLed::On) m_4bitInputValue |= 0x02;
if (m_base->group4BitInputLED0->state() == KLed::On) m_4bitInputValue |= 0x01;
m_base->group4BitInputValueText->setText(TQString("0x%1").arg(m_4bitInputValue, 0, 16));
}
void FPGAViewPart::process4BitOutputChanges() {
// Write m_4bitOutputValue to LEDs
m_base->group4BitOutputLED3->setState((m_4bitOutputValue & 0x08)?KLed::On:KLed::Off);
m_base->group4BitOutputLED2->setState((m_4bitOutputValue & 0x04)?KLed::On:KLed::Off);
m_base->group4BitOutputLED1->setState((m_4bitOutputValue & 0x02)?KLed::On:KLed::Off);
m_base->group4BitOutputLED0->setState((m_4bitOutputValue & 0x01)?KLed::On:KLed::Off);
// Write m_4bitOutputValue to label
m_base->group4BitOutputValueText->setText(TQString("0x%1").arg(m_4bitOutputValue, 0, 16));
}
void FPGAViewPart::process8BitInputChanges() {
if (m_remoteInputModeEnabled) {
// Read LED status into m_8bitInputValue
m_8bitInputValue = 0;
if (m_base->group8BitInputLED7->state() == KLed::On) m_8bitInputValue |= 0x80;
if (m_base->group8BitInputLED6->state() == KLed::On) m_8bitInputValue |= 0x40;
if (m_base->group8BitInputLED5->state() == KLed::On) m_8bitInputValue |= 0x20;
if (m_base->group8BitInputLED4->state() == KLed::On) m_8bitInputValue |= 0x10;
if (m_base->group8BitInputLED3->state() == KLed::On) m_8bitInputValue |= 0x08;
if (m_base->group8BitInputLED2->state() == KLed::On) m_8bitInputValue |= 0x04;
if (m_base->group8BitInputLED1->state() == KLed::On) m_8bitInputValue |= 0x02;
if (m_base->group8BitInputLED0->state() == KLed::On) m_8bitInputValue |= 0x01;
m_base->group8BitInputLED7->setClickable(true);
m_base->group8BitInputLED6->setClickable(true);
m_base->group8BitInputLED5->setClickable(true);
m_base->group8BitInputLED4->setClickable(true);
m_base->group8BitInputLED3->setClickable(true);
m_base->group8BitInputLED2->setClickable(true);
m_base->group8BitInputLED1->setClickable(true);
m_base->group8BitInputLED0->setClickable(true);
}
else {
// Write m_8bitInputValue to LEDs
m_base->group8BitInputLED7->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
m_base->group8BitInputLED6->setState((m_8bitInputValue & 0x40)?KLed::On:KLed::Off);
m_base->group8BitInputLED5->setState((m_8bitInputValue & 0x20)?KLed::On:KLed::Off);
m_base->group8BitInputLED4->setState((m_8bitInputValue & 0x10)?KLed::On:KLed::Off);
m_base->group8BitInputLED3->setState((m_8bitInputValue & 0x08)?KLed::On:KLed::Off);
m_base->group8BitInputLED2->setState((m_8bitInputValue & 0x04)?KLed::On:KLed::Off);
m_base->group8BitInputLED1->setState((m_8bitInputValue & 0x02)?KLed::On:KLed::Off);
m_base->group8BitInputLED0->setState((m_8bitInputValue & 0x01)?KLed::On:KLed::Off);
m_base->group8BitInputLED7->setClickable(false);
m_base->group8BitInputLED6->setClickable(false);
m_base->group8BitInputLED5->setClickable(false);
m_base->group8BitInputLED4->setClickable(false);
m_base->group8BitInputLED3->setClickable(false);
m_base->group8BitInputLED2->setClickable(false);
m_base->group8BitInputLED1->setClickable(false);
m_base->group8BitInputLED0->setClickable(false);
}
m_base->group8BitInputValueText->setText(TQString("").sprintf("0x%02x", m_8bitInputValue));
if (m_remoteInputModeEnabled) {
m_base->group8BitInput->setTitle(i18n("8-Bit Input (Switches)") + " [" + i18n("Remote Input Mode") + "]");
}
else {
m_base->group8BitInput->setTitle(i18n("8-Bit Input (Switches)") + " [" + i18n("Local Input Mode") + "]");
}
}
void FPGAViewPart::update8BitInputLEDs() {
// Write m_8bitInputValue to LEDs
m_base->group8BitInputLED7->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
m_base->group8BitInputLED6->setState((m_8bitInputValue & 0x40)?KLed::On:KLed::Off);
m_base->group8BitInputLED5->setState((m_8bitInputValue & 0x20)?KLed::On:KLed::Off);
m_base->group8BitInputLED4->setState((m_8bitInputValue & 0x10)?KLed::On:KLed::Off);
m_base->group8BitInputLED3->setState((m_8bitInputValue & 0x08)?KLed::On:KLed::Off);
m_base->group8BitInputLED2->setState((m_8bitInputValue & 0x04)?KLed::On:KLed::Off);
m_base->group8BitInputLED1->setState((m_8bitInputValue & 0x02)?KLed::On:KLed::Off);
m_base->group8BitInputLED0->setState((m_8bitInputValue & 0x01)?KLed::On:KLed::Off);
}
void FPGAViewPart::process8BitOutputChanges() {
// Write m_8bitOutputValue to LEDs
m_base->group8BitOutputLED7->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
m_base->group8BitOutputLED6->setState((m_8bitOutputValue & 0x40)?KLed::On:KLed::Off);
m_base->group8BitOutputLED5->setState((m_8bitOutputValue & 0x20)?KLed::On:KLed::Off);
m_base->group8BitOutputLED4->setState((m_8bitOutputValue & 0x10)?KLed::On:KLed::Off);
m_base->group8BitOutputLED3->setState((m_8bitOutputValue & 0x08)?KLed::On:KLed::Off);
m_base->group8BitOutputLED2->setState((m_8bitOutputValue & 0x04)?KLed::On:KLed::Off);
m_base->group8BitOutputLED1->setState((m_8bitOutputValue & 0x02)?KLed::On:KLed::Off);
m_base->group8BitOutputLED0->setState((m_8bitOutputValue & 0x01)?KLed::On:KLed::Off);
m_base->group8BitOutputValueText->setText(TQString("").sprintf("0x%02x", m_8bitOutputValue));
}
void FPGAViewPart::process16BitInputChanges() {
// Read input into m_16bitInputValue
m_16bitInputValue = m_base->group16BitInputValue->value();
}
void FPGAViewPart::process16BitOutputChanges() {
// Write m_16bitOutputValue to label
m_base->group16BitOutputValue->setText(TQString("").sprintf("0x%04x", m_16bitOutputValue));
}
void FPGAViewPart::processLCDOutputChanges() {
// Write m_LCDOutputValue to label
m_base->LCDOutputLabel->setText(m_LCDOutputValue);
}
void FPGAViewPart::process7SegmentLEDOutputChanges() {
// Write LED digits to 7 segment displays
// Note that the information stored in the data structures is bitwise inverted
m_base->LEDOutputDisplayDigit0->setLitSegments(~m_7segDigit0OutputValue);
m_base->LEDOutputDisplayDigit1->setLitSegments(~m_7segDigit1OutputValue);
m_base->LEDOutputDisplayDigit2->setLitSegments(~m_7segDigit2OutputValue);
m_base->LEDOutputDisplayDigit3->setLitSegments(~m_7segDigit3OutputValue);
}
void FPGAViewPart::processLockouts() {
TQWidget* mainWidget = widget();
if (mainWidget) {
if ((m_socket) && (m_socket->state() == TQSocket::Connected) && (connToServerState > 0) && (connToServerConnecting == false)) {
mainWidget->setEnabled(true);
}
else {
mainWidget->setEnabled(false);
}
}
// Interface mode switching handlers
if (m_interfaceMode == BasicInterfaceMode) {
m_modeBasicEnabled->setChecked(true);
m_modeIntermediateEnabled->setChecked(false);
m_modeAdvancedEnabled->setChecked(false);
m_base->groupLCDDisplay->show();
m_base->groupLEDDisplay->hide();
m_base->groupBatchTest->hide();
m_base->groupDataProcessing->hide();
m_base->groupInputImage->hide();
m_base->groupOutputImage->hide();
if (m_inputImageViewer) {
mdiMainForm()->closeWindow(m_inputImageViewer);
m_inputImageViewer = NULL;
}
if (m_outputImageViewer) {
mdiMainForm()->closeWindow(m_outputImageViewer);
m_outputImageViewer = NULL;
}
}
if (m_interfaceMode == IntermediateInterfaceMode) {
m_modeBasicEnabled->setChecked(false);
m_modeIntermediateEnabled->setChecked(true);
m_modeAdvancedEnabled->setChecked(false);
m_base->groupLCDDisplay->show();
m_base->groupLEDDisplay->show();
m_base->groupBatchTest->show();
m_base->groupDataProcessing->hide();
m_base->groupInputImage->hide();
m_base->groupOutputImage->hide();
if (m_inputImageViewer) {
mdiMainForm()->closeWindow(m_inputImageViewer);
m_inputImageViewer = NULL;
}
if (m_outputImageViewer) {
mdiMainForm()->closeWindow(m_outputImageViewer);
m_outputImageViewer = NULL;
}
}
if (m_interfaceMode == AdvancedInterfaceMode) {
m_modeBasicEnabled->setChecked(false);
m_modeIntermediateEnabled->setChecked(false);
m_modeAdvancedEnabled->setChecked(true);
m_base->groupLCDDisplay->show();
m_base->groupLEDDisplay->show();
m_base->groupBatchTest->show();
m_base->groupDataProcessing->show();
m_base->groupInputImage->show();
m_base->groupOutputImage->show();
if (!m_inputImageViewer) {
m_inputImageViewer = new ImageViewerWindow(i18n("Remote FPGA Input Image"));
mdiMainForm()->addWindow(m_inputImageViewer);
m_inputImageViewer->resize(m_dataMemoryImageWidth, m_dataMemoryImageHeight);
}
if (!m_outputImageViewer) {
m_outputImageViewer = new ImageViewerWindow(i18n("Remote FPGA Output Image"));
mdiMainForm()->addWindow(m_outputImageViewer);
m_outputImageViewer->resize(m_dataMemoryImageWidth, m_dataMemoryImageHeight);
}
}
if ((m_base->batchTestInputFile->url() != "") && (m_base->batchTestOutputFile->url() != "") && (m_commHandlerMode == 0) && (m_connectionActiveAndValid == true)) {
m_base->batchTestRunButton->setEnabled(true);
}
else {
m_base->batchTestRunButton->setEnabled(false);
}
if (m_commHandlerMode == 1) {
m_base->batchTestInputFile->setEnabled(false);
m_base->batchTestOutputFile->setEnabled(false);
m_base->batchTest16BitCheckBox->setEnabled(false);
m_base->batchTestRunButton->setEnabled(false);
m_base->groupGlobalControlResetButton->setEnabled(false);
}
else {
m_base->batchTestInputFile->setEnabled(true);
m_base->batchTestOutputFile->setEnabled(true);
m_base->batchTest16BitCheckBox->setEnabled(true);
}
if ((m_connectionActiveAndValid == true) && (m_commHandlerMode == 0)) {
m_base->batchTestStatusLabel->setText(i18n("Ready"));
}
if ((m_base->dataProcessingInputFile->url() != "") && (m_base->dataProcessingOutputFile->url() != "") && (m_commHandlerMode == 0) && (m_connectionActiveAndValid == true)) {
m_base->dataProcessingRunButton->setEnabled(true);
}
else {
m_base->dataProcessingRunButton->setEnabled(false);
}
if (m_commHandlerMode == 2) {
m_base->dataProcessingInputFile->setEnabled(false);
m_base->dataProcessingOutputFile->setEnabled(false);
m_base->dataProcessingGenerateValidationString->setEnabled(false);
m_base->dataProcessingRunButton->setEnabled(false);
m_base->groupGlobalControlResetButton->setEnabled(false);
}
else {
m_base->dataProcessingInputFile->setEnabled(true);
m_base->dataProcessingOutputFile->setEnabled(true);
// FIXME
// Re-enable this when a good way to implement it (using Kerberos?) is found!
//m_base->dataProcessingGenerateValidationString->setEnabled(true);
m_base->dataProcessingGenerateValidationString->setEnabled(false);
}
if ((m_connectionActiveAndValid == true) && (m_commHandlerMode == 0)) {
m_base->dataProcessingStatusLabel->setText(i18n("Ready"));
m_base->groupGlobalControlResetButton->setEnabled(!m_sendingUserLogicReset);
}
}
void FPGAViewPart::resizeToHint() {
resize(widget()->sizeHint());
}
void FPGAViewPart::switchToBasicMode() {
m_interfaceMode = BasicInterfaceMode;
processLockouts();
TQTimer::singleShot(0, this, SLOT(resizeToHint()));
}
void FPGAViewPart::switchToIntermediateMode() {
m_interfaceMode = IntermediateInterfaceMode;
processLockouts();
TQTimer::singleShot(0, this, SLOT(resizeToHint()));
}
void FPGAViewPart::switchToAdvancedMode() {
m_interfaceMode = AdvancedInterfaceMode;
processLockouts();
TQTimer::singleShot(0, this, SLOT(resizeToHint()));
}
void FPGAViewPart::connectionClosed() {
closeURL();
}
void FPGAViewPart::postInit() {
processAllGraphicsUpdates();
setUsingFixedSize(true);
connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateDisplay()));
connect(m_timeoutTimer, SIGNAL(timeout()), this, SLOT(updateDisplay()));
}
bool FPGAViewPart::openURL(const KURL &url) {
int ret;
ret = connectToServer(url.url());
processLockouts();
return (ret != 0);
}
bool FPGAViewPart::closeURL() {
disconnectFromServer();
m_url = KURL();
return true;
}
void FPGAViewPart::disconnectFromServerCallback() {
m_updateTimer->stop();
m_timeoutTimer->stop();
}
void FPGAViewPart::connectionFinishedCallback() {
connect(m_socket, SIGNAL(readyRead()), m_socket, SLOT(processPendingData()));
m_socket->processPendingData();
connect(m_socket, SIGNAL(newDataReceived()), this, SLOT(updateDisplay()));
m_tickerState = 0;
m_commHandlerState = 0;
m_commHandlerMode = 0;
m_commHandlerNextState = 0;
m_commHandlerNextMode = 0;
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE);
processLockouts();
updateDisplay();
return;
}
void FPGAViewPart::connectionStatusChangedCallback() {
processLockouts();
}
TQPtrList<TDEAction> FPGAViewPart::menuActionList() {
return m_menuActionList;
}
void FPGAViewPart::groupGlobalControlResetButtonClicked() {
m_sendingUserLogicReset = true;
processLockouts();
}
void FPGAViewPart::batchTestRunButtonClicked() {
m_commHandlerNextState = 0;
m_commHandlerNextMode = 1;
m_batchUsing16Bit = m_base->batchTest16BitCheckBox->isChecked();
processLockouts();
}
void FPGAViewPart::dataProcessingRunButtonClicked() {
m_commHandlerNextState = 0;
m_commHandlerNextMode = 2;
m_dataGenerateValidationString = m_base->dataProcessingGenerateValidationString->isChecked();
processLockouts();
}
void FPGAViewPart::sendInputStatesToRemoteFPGA() {
if (m_socket) {
char data[64];
process4BitInputChanges();
process8BitInputChanges();
process16BitInputChanges();
// 4-bit inputs
data[0] = 'I';
data[1] = '\r';
data[2] = m_4bitInputValue;
data[3] = '\r';
// 8-bit inputs
data[4] = 'B';
data[5] = '\r';
data[6] = m_8bitInputValue;
data[7] = '\r';
// 16-bit inputs
data[8] = 'C';
data[9] = '\r';
data[10] = (m_16bitInputValue&0xff00)>>8;
data[11] = '\r';
data[12] = m_16bitInputValue&0xff;
data[13] = '\r';
m_socket->writeBlock(data, 14);
m_socket->writeBufferedData();
if (m_sendingUserLogicReset) {
// Send user logic reset request
data[0] = 'R';
data[1] = '\r';
m_socket->writeBlock(data, 2);
m_socket->writeBufferedData();
m_sendingUserLogicReset = false;
processLockouts();
}
}
}
void FPGAViewPart::receiveInputStatesFromRemoteFPGA() {
if (m_socket) {
char data[64];
// LCD
m_socket->readBlock(data, 32);
char line[34];
memcpy(line, data, 16);
line[16] = '\n';
memcpy(line+17, data+16, 16);
line[33] = 0;
m_LCDOutputValue = line;
// Remote/Local input mode
m_socket->readBlock(data, 1);
if (data[0] == 0) {
// Local mode
m_remoteInputModeEnabled = false;
}
else {
// Remote mode
m_remoteInputModeEnabled = true;
}
// DSP RAM size
m_socket->readBlock(data, 1);
m_dataMemorySize = pow(2, data[0]);
if (m_dataMemorySize != m_dataMemorySizePrev) {
unsigned int newSize = round(sqrt(m_dataMemorySize));
m_dataMemoryImageWidth = newSize;
m_dataMemoryImageHeight = newSize;
m_base->groupInputImage->setTitle(TQString("Input Image (%1x%2):").arg(m_dataMemoryImageWidth).arg(m_dataMemoryImageHeight));
m_base->groupOutputImage->setTitle(TQString("Output Image (%1x%2):").arg(m_dataMemoryImageWidth).arg(m_dataMemoryImageHeight));
if (m_inputImageViewer) {
m_inputImageViewer->resize(m_dataMemoryImageWidth, m_dataMemoryImageHeight);
}
if (m_outputImageViewer) {
m_outputImageViewer->resize(m_dataMemoryImageWidth, m_dataMemoryImageHeight);
}
m_dataMemorySizePrev = m_dataMemorySize;
}
// 4-bit outputs
m_socket->readBlock(data, 1);
m_4bitOutputValue = data[0];
// 8-bit outputs
m_socket->readBlock(data, 1);
m_8bitOutputValue = data[0];
// 16-bit outputs
m_socket->readBlock(data, 2);
m_16bitOutputValue = (data[0] << 8) | data[1];
// 7-segment LED display
m_socket->readBlock(data, 4);
m_7segDigit3OutputValue = data[0];
m_7segDigit2OutputValue = data[1];
m_7segDigit1OutputValue = data[2];
m_7segDigit0OutputValue = data[3];
// Write changes to GUI
process4BitOutputChanges();
process8BitInputChanges();
process8BitOutputChanges();
process16BitOutputChanges();
processLCDOutputChanges();
process7SegmentLEDOutputChanges();
}
}
#define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \
m_tickerState = 0; \
m_commHandlerState = 0; \
m_commHandlerMode = 0; \
m_commHandlerNextState = 0; \
m_commHandlerNextMode = 0; \
while (m_socket->bytesAvailable() > 0) { \
m_socket->readBlock(data, 64); \
} \
setStatusMessage(i18n("Debug interface timeout, still waiting for data. Please verify that the FPGA is properly configured.")); \
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE); \
return;
#define POLL_FOR_DATA_IMMEDIATE if (!m_updateTimer->isActive()) { \
m_updateTimer->start(10, TRUE); \
}
void FPGAViewPart::updateDisplay() {
if (m_socket) {
char data[64];
if (m_commHandlerMode == 0) {
// Normal operation
switch (m_commHandlerState) {
case 0:
// Send current input states to remote system
sendInputStatesToRemoteFPGA();
// Clear input buffer to ensure proper sync
m_socket->clearIncomingData();
// Send request for all output states
m_socket->writeLine("L\r");
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE);
m_commHandlerState = 1;
POLL_FOR_DATA_IMMEDIATE
break;
case 1:
// Get all data
if (m_socket->bytesAvailable() >= 42) {
if (m_socket->bytesAvailable() == 42) {
// Process the received data packet
receiveInputStatesFromRemoteFPGA();
m_connectionActiveAndValid = true;
TQString tickerChar;
switch (m_tickerState) {
case 0:
tickerChar = "-";
break;
case 1:
tickerChar = "\\";
break;
case 2:
tickerChar = "|";
break;
case 3:
tickerChar = "/";
break;
}
setStatusMessage(i18n("Running") + TQString("... %1").arg(tickerChar));
m_tickerState++;
if (m_tickerState > 3) {
m_tickerState = 0;
}
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE);
m_commHandlerState = m_commHandlerNextState;
m_commHandlerMode = m_commHandlerNextMode;
m_commHandlerNextState = 0;
m_commHandlerNextMode = 0;
POLL_FOR_DATA_IMMEDIATE
}
else {
// Invalid data packet
// State likely lost in remote debug module (e.g. FPGA reprogrammed)
// Clear input buffers and allow timeout to occur in order to force resync
m_socket->clearIncomingData();
}
}
else {
if (!m_timeoutTimer->isActive()) {
UPDATEDISPLAY_TIMEOUT
}
else {
POLL_FOR_DATA_IMMEDIATE
}
}
break;
}
processLockouts();
}
else if (m_commHandlerMode == 1) {
// Batch test mode
// This expects to see a newline-delimited text file containing input values to test
if (m_commHandlerState == 0) {
processLockouts();
m_base->batchTestStatusLabel->setText(i18n("Reading input data") + "...");
m_batchInputValueList.clear();
TQFile file(m_base->batchTestInputFile->url());
if (file.open(IO_ReadOnly)) {
TQTextStream stream(&file);
TQString line;
while (!stream.atEnd()) {
line = stream.readLine();
m_batchInputValueList.append(line.toUInt());
}
file.close();
m_base->batchTestProgressBar->setTotalSteps(m_batchInputValueList.count());
m_batchOutputFile = new TQFile(m_base->batchTestOutputFile->url());
if (m_batchOutputFile->open(IO_ReadWrite | IO_Truncate)) {
m_batchCurrentValueIndex = 0;
m_commHandlerState = 1;
POLL_FOR_DATA_IMMEDIATE
}
else {
delete m_batchOutputFile;
m_batchOutputFile = NULL;
KMessageBox::error(0, i18n("<qt>Unable to open selected batch output file</qt>"), i18n("Batch Failed"));
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->batchTestProgressBar->reset();
processLockouts();
}
}
else {
KMessageBox::error(0, i18n("<qt>Unable to open selected batch input file</qt>"), i18n("Batch Failed"));
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->batchTestProgressBar->reset();
processLockouts();
}
}
else if (m_commHandlerState == 1) {
if (m_batchCurrentValueIndex >= m_batchInputValueList.count()) {
// Done!
m_batchOutputFile->flush();
m_batchOutputFile->close();
delete m_batchOutputFile;
m_batchOutputFile = NULL;
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->batchTestProgressBar->reset();
processLockouts();
}
else {
m_base->batchTestStatusLabel->setText(i18n("Processing element") + " " + TQString("%1/%2").arg(m_batchCurrentValueIndex).arg(m_batchInputValueList.count()) + "...");
if (m_batchUsing16Bit) {
m_16bitInputValue = m_batchInputValueList[m_batchCurrentValueIndex];
}
else {
m_8bitInputValue = m_batchInputValueList[m_batchCurrentValueIndex];
update8BitInputLEDs();
}
sendInputStatesToRemoteFPGA();
// Clear input buffer to ensure proper sync
m_socket->clearIncomingData();
// Send request for all output states
m_socket->writeLine("L\r");
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE);
m_commHandlerState = 2;
POLL_FOR_DATA_IMMEDIATE
}
}
else if (m_commHandlerState == 2) {
// Get all data
if (m_socket->bytesAvailable() >= 42) {
if (m_socket->bytesAvailable() == 42) {
TQString line;
// Process the received data packet
receiveInputStatesFromRemoteFPGA();
// Write received data to batch output file
if (m_batchUsing16Bit) {
line = TQString("%1\n").arg(m_16bitOutputValue);
}
else {
line = TQString("%1\n").arg(m_8bitOutputValue);
}
m_batchOutputFile->writeBlock(line.ascii(), line.length());
m_base->batchTestProgressBar->setProgress(m_batchCurrentValueIndex);
m_batchCurrentValueIndex++;
m_connectionActiveAndValid = true;
setStatusMessage(i18n("Running batch test") + "...");
m_timeoutTimer->start(FPGA_COMM_TIMEOUT_MS, TRUE);
m_commHandlerState = 1;
POLL_FOR_DATA_IMMEDIATE
}
else {
// Invalid data packet
// State likely lost in remote debug module (e.g. FPGA reprogrammed)
// Clear input buffers and allow timeout to occur in order to force resync
m_socket->clearIncomingData();
}
}
else {
if (!m_timeoutTimer->isActive()) {
m_batchOutputFile->flush();
m_batchOutputFile->close();
delete m_batchOutputFile;
m_batchOutputFile = NULL;
m_base->batchTestProgressBar->reset();
m_commHandlerMode = 0;
m_commHandlerState = 0;
processLockouts();
UPDATEDISPLAY_TIMEOUT
}
}
}
}
else if (m_commHandlerMode == 2) {
// Data processing mode
// This detects when the incoming data file is a picture (bmp, png, etc.) and processes it accordingly
int i;
if (m_commHandlerState == 0) {
m_timeoutTimer->stop();
processLockouts();
m_base->dataProcessingStatusLabel->setText(i18n("Reading input data") + "...");
m_batchInputValueList.clear();
TQFile file(m_base->dataProcessingInputFile->url());
if (file.open(IO_ReadOnly)) {
// Is it an image?
m_dataIsImage = m_dataInputImage.load(m_base->dataProcessingInputFile->url());
if ((file.size() <= m_dataMemorySize) || ((m_dataIsImage) && ((m_dataInputImage.height()*m_dataInputImage.width()) <= m_dataMemorySize))) {
m_base->dataProcessingProgressBar->setTotalSteps(0);
m_base->dataProcessingProgressBar->setProgress(0);
m_dataOutputFile = new TQFile(m_base->dataProcessingOutputFile->url());
if (m_dataOutputFile->open(IO_ReadWrite)) {
if (!m_dataIsImage) {
m_dataByteArray = file.readAll();
}
else {
// Create grayscale input image buffer
TQImage displayImage = m_dataInputImage;
// Populate m_dataByteArray and displayImage with image data
int x;
int y;
unsigned char pixel_value;
int imageWidth = m_dataInputImage.width();
m_dataByteArray.resize(m_dataInputImage.height()*imageWidth);
for (y=0; y<m_dataInputImage.height(); y++) {
for (x=0; x<m_dataInputImage.width(); x++) {
pixel_value = tqGray(m_dataInputImage.pixel(x,y));
m_dataByteArray[(y*imageWidth)+x] = pixel_value;
displayImage.setPixel(x, y, tqRgb(pixel_value, pixel_value, pixel_value));
}
}
// Show image in GUI
TQPixmap inputImagePixmap(displayImage);
TQImage scaledDisplayImage = displayImage;
scaledDisplayImage = scaledDisplayImage.smoothScale(m_base->ImageInputLabel->width(), m_base->ImageInputLabel->height());
TQPixmap scaledInputImagePixmap(scaledDisplayImage);
m_base->ImageInputLabel->setPixmap(scaledInputImagePixmap);
m_inputImageViewer->setPixmap(inputImagePixmap);
}
m_base->dataProcessingStatusLabel->setText(i18n("Transmitting data to FPGA") + "...");
// Transmit m_dataByteArray to FPGA
m_socket->writeBlock("M\r", 2);
m_socket->writeBufferedData();
int len = m_dataByteArray.size();
int txlen = m_dataMemorySize;
if (len >= txlen) {
len = txlen;
}
TQByteArray dataToSend(m_dataMemorySize);
for (i=0; i<len; i++) {
dataToSend[i] = m_dataByteArray[i];
}
for (; i<txlen; i++) {
dataToSend[i] = 0;
}
m_base->dataProcessingProgressBar->setTotalSteps(txlen*2);
m_base->dataProcessingProgressBar->setProgress(0);
int offset = 0;
while (offset < txlen) {
m_socket->writeBlock(dataToSend.data()+offset, 1024);
m_socket->writeBufferedData();
offset = offset + 1024;
m_base->dataProcessingProgressBar->setProgress(offset);
}
m_timeoutTimer->start(FPGA_DATA_PROCESSING_TIMEOUT_MS, TRUE);
m_batchCurrentValueIndex = 0;
m_commHandlerState = 1;
POLL_FOR_DATA_IMMEDIATE
}
else {
KMessageBox::error(0, i18n("<qt>Unable to open selected data output file</qt>"), i18n("Data Processing Failed"));
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->dataProcessingProgressBar->reset();
processLockouts();
}
}
else {
KMessageBox::error(0, i18n("<qt>Selected data input file exceeds the maximum allowed size of 16,384 bytes</qt>"), i18n("Data Processing Failed"));
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->dataProcessingProgressBar->reset();
processLockouts();
}
}
else {
KMessageBox::error(0, i18n("<qt>Unable to open selected data input file</qt>"), i18n("Data Processing Failed"));
m_commHandlerMode = 0;
m_commHandlerState = 0;
m_base->dataProcessingProgressBar->reset();
processLockouts();
}
}
else if (m_commHandlerState == 1) {
if (m_socket->bytesAvailable() >= 1) {
TQByteArray recData(1);
m_socket->readBlock(recData.data(), 1);
m_base->dataProcessingStatusLabel->setText(i18n("Waiting for data from FPGA") + "...");
m_timeoutTimer->start(FPGA_DATA_PROCESSING_TIMEOUT_MS, TRUE);
m_commHandlerState = 2;
POLL_FOR_DATA_IMMEDIATE
}
else {
if (!m_timeoutTimer->isActive()) {
m_dataOutputFile->flush();
m_dataOutputFile->close();
delete m_dataOutputFile;
m_dataOutputFile = NULL;
m_base->dataProcessingProgressBar->reset();
m_commHandlerMode = 0;
m_commHandlerState = 0;
KMessageBox::error(0, i18n("<qt>Timeout occurred while attempting to transmit data to FPGA</qt>"), i18n("Data Processing Failed"));
processLockouts();
UPDATEDISPLAY_TIMEOUT
}
}
}
else if (m_commHandlerState == 2) {
if (m_socket->bytesAvailable() >= m_dataMemorySize) {
TQByteArray recData(m_dataMemorySize);
int offset = 0;
while (offset < m_dataMemorySize) {
m_socket->readBlock(recData.data()+offset, 1024);
offset = offset + 1024;
}
m_base->dataProcessingStatusLabel->setText(i18n("Writing data to file") + "...");
if (!m_dataIsImage) {
// Write data straight to file
m_dataOutputFile->writeBlock(recData);
m_base->ImageOutputLabel->setPixmap(TQPixmap());
m_outputImageViewer->setPixmap(TQPixmap());
}
else {
// Write data to image, then write image to file
TQImage outputImage(m_dataInputImage.width(), m_dataInputImage.height(), m_dataInputImage.depth());
int x;
int y;
unsigned char grey;
int imageWidth = outputImage.width();
m_dataByteArray.resize(outputImage.height()*imageWidth);
for (y=0; y<outputImage.height(); y++) {
for (x=0; x<outputImage.width(); x++) {
grey = recData[(y*imageWidth)+x];
outputImage.setPixel(x, y, tqRgb(grey, grey, grey));
}
}
TQPixmap outputImagePixmap(outputImage);
TQImage scaledOutputImage = outputImage;
scaledOutputImage = scaledOutputImage.smoothScale(m_base->ImageOutputLabel->width(), m_base->ImageOutputLabel->height());
TQPixmap scaledOutputImagePixmap(scaledOutputImage);
m_base->ImageOutputLabel->setPixmap(scaledOutputImagePixmap);
m_outputImageViewer->setPixmap(outputImagePixmap);
outputImage.save(m_dataOutputFile, "PNG");
}
m_dataOutputFile->flush();
// Calculate signature and write metadata to verification file
m_dataOutputFile->reset();
TQByteArray writtenFile = m_dataOutputFile->readAll();
KMD5 writtenMD5(writtenFile);
TQFile verificationFile(m_base->dataProcessingOutputFile->url() + ".vrf");
if (verificationFile.open(IO_ReadWrite)) {
TQCString datastring = writtenMD5.hexDigest();
datastring.prepend("md5=");
verificationFile.writeBlock(datastring);
datastring = (TQString("datetime=%1").arg(TQDateTime::currentDateTime().toString())).ascii();
verificationFile.writeBlock(datastring);
}
m_dataOutputFile->close();
delete m_dataOutputFile;
m_dataOutputFile = NULL;
m_base->dataProcessingProgressBar->reset();
m_commHandlerMode = 0;
m_commHandlerState = 0;
processLockouts();
POLL_FOR_DATA_IMMEDIATE
}
else {
// Update the GUI with status information
m_base->dataProcessingProgressBar->setProgress(m_dataMemorySize + m_socket->bytesAvailable());
if (m_socket->bytesAvailable() > 0) {
m_base->dataProcessingStatusLabel->setText(i18n("Receiving data from FPGA") + "...");
}
if (!m_timeoutTimer->isActive()) {
m_dataOutputFile->flush();
m_dataOutputFile->close();
delete m_dataOutputFile;
m_dataOutputFile = NULL;
m_base->dataProcessingProgressBar->reset();
m_commHandlerMode = 0;
m_commHandlerState = 0;
KMessageBox::error(0, i18n("<qt>Timeout occurred while attempting to receive data from FPGA</qt>"), i18n("Data Processing Failed"));
processLockouts();
UPDATEDISPLAY_TIMEOUT
}
}
}
}
}
else {
m_commHandlerState = 0;
m_commHandlerMode = 0;
}
}
TDEAboutData* FPGAViewPart::createAboutData() {
return new TDEAboutData( APP_NAME, I18N_NOOP( APP_PRETTYNAME ), APP_VERSION );
}
} //namespace RemoteLab
#include "part.moc"