|
|
|
/*
|
|
|
|
* 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 Timothy Pearson
|
|
|
|
* Raptor Engineering
|
|
|
|
* http://www.raptorengineeringinc.com
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "define.h"
|
|
|
|
#include "part.h"
|
|
|
|
|
|
|
|
#include <kaboutdata.h> //::createAboutData()
|
|
|
|
#include <tdeaction.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kmessagebox.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 <tqpainter.h>
|
|
|
|
|
|
|
|
#include "tracewidget.h"
|
|
|
|
#include "floatspinbox.h"
|
|
|
|
#include "layout.h"
|
|
|
|
|
|
|
|
#define SERVER_TIMEOUT_MS 10000
|
|
|
|
#define FPGA_COMM_TIMEOUT_MS 500
|
|
|
|
#define FPGA_DATA_PROCESSING_TIMEOUT_MS 2500
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FPGA7Segment::FPGA7Segment( TQWidget *parent, const char *name )
|
|
|
|
: TQFrame( parent, name )
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
FPGA7Segment::~FPGA7Segment() {
|
|
|
|
free(m_prevSegments);
|
|
|
|
free(m_currentSegments);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::init() {
|
|
|
|
setFrameStyle(TQFrame::Box | TQFrame::Raised);
|
|
|
|
val = 0;
|
|
|
|
smallPoint = TRUE;
|
|
|
|
setSegmentStyle(Flat);
|
|
|
|
m_prevSegments = (char*)malloc(sizeof(char)*9);
|
|
|
|
m_currentSegments = (char*)malloc(sizeof(char)*9);
|
|
|
|
m_prevSegments[0] = 99;
|
|
|
|
m_currentSegments[0] = 99;
|
|
|
|
d = 0;
|
|
|
|
setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::setLitSegments(unsigned int segs) {
|
|
|
|
// This produces an array of up to 10 chars, with each char being the number of a lit segment, and the list being terminated with the number 99
|
|
|
|
// The bit input in segs is active high
|
|
|
|
// The bit sequence, MSB to LSB, is dp a b c d e f g
|
|
|
|
// Segment letters are taken from ug130.pdf
|
|
|
|
// 0: a
|
|
|
|
// 1: f
|
|
|
|
// 2: d
|
|
|
|
// 3: g
|
|
|
|
// 4: e
|
|
|
|
// 5: c
|
|
|
|
// 6: b
|
|
|
|
// 7: dp
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
if (segs & 0x80) { m_currentSegments[i] = 7; i++; }
|
|
|
|
if (segs & 0x40) { m_currentSegments[i] = 0; i++; }
|
|
|
|
if (segs & 0x20) { m_currentSegments[i] = 6; i++; }
|
|
|
|
if (segs & 0x10) { m_currentSegments[i] = 5; i++; }
|
|
|
|
if (segs & 0x08) { m_currentSegments[i] = 2; i++; }
|
|
|
|
if (segs & 0x04) { m_currentSegments[i] = 4; i++; }
|
|
|
|
if (segs & 0x02) { m_currentSegments[i] = 1; i++; }
|
|
|
|
if (segs & 0x01) { m_currentSegments[i] = 3; i++; }
|
|
|
|
m_currentSegments[i] = 99;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::drawContents( TQPainter *p )
|
|
|
|
{
|
|
|
|
// Draw all segments
|
|
|
|
TQPoint pos;
|
|
|
|
int digitSpace = smallPoint ? 2 : 1;
|
|
|
|
int xSegLen = width()*5/(1*(5 + digitSpace) + digitSpace);
|
|
|
|
int ySegLen = height()*5/12;
|
|
|
|
int segLen = ySegLen > xSegLen ? xSegLen : ySegLen;
|
|
|
|
int xAdvance = segLen*( 5 + 1 )/5;
|
|
|
|
int xOffset = ( width() - xAdvance + segLen/5 )/2;
|
|
|
|
int yOffset = ( height() - segLen*2 )/2;
|
|
|
|
|
|
|
|
pos = TQPoint(xOffset, yOffset);
|
|
|
|
drawDigit(pos, *p, segLen, m_currentSegments);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSize FPGA7Segment::sizeHint() const {
|
|
|
|
return TQSize(10 + 9 * (1 + (smallPoint ? 0 : 1)), 23);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::setSegmentStyle( SegmentStyle s ) {
|
|
|
|
fill = (s == Flat || s == Filled);
|
|
|
|
shadow = (s == Outline || s == Filled);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
FPGA7Segment::SegmentStyle FPGA7Segment::segmentStyle() const {
|
|
|
|
Q_ASSERT(fill || shadow);
|
|
|
|
if (!fill && shadow) {
|
|
|
|
return Outline;
|
|
|
|
}
|
|
|
|
if (fill && shadow) {
|
|
|
|
return Filled;
|
|
|
|
}
|
|
|
|
return Flat;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void addPoint( TQPointArray &a, const TQPoint &p ) {
|
|
|
|
uint n = a.size();
|
|
|
|
a.resize(n + 1);
|
|
|
|
a.setPoint(n, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::drawDigit(const TQPoint &pos, TQPainter &p, int segLen, const char *newSegs) {
|
|
|
|
char updates[20][2]; // Can hold 2 times number of segments, only
|
|
|
|
// first 10 used if segment table is correct
|
|
|
|
int nErases;
|
|
|
|
int nUpdates;
|
|
|
|
const char *segs;
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
const char erase = 0;
|
|
|
|
const char draw = 1;
|
|
|
|
const char leaveAlone = 2;
|
|
|
|
|
|
|
|
segs = m_prevSegments;
|
|
|
|
for ( nErases=0; segs[nErases] != 99; nErases++ ) {
|
|
|
|
updates[nErases][0] = erase; // Get segments to erase to
|
|
|
|
updates[nErases][1] = segs[nErases]; // remove old char
|
|
|
|
}
|
|
|
|
nUpdates = nErases;
|
|
|
|
segs = newSegs;
|
|
|
|
for(i = 0 ; segs[i] != 99 ; i++) {
|
|
|
|
for ( j=0; j<nErases; j++ ) {
|
|
|
|
if ( segs[i] == updates[j][1] ) { // Same segment ?
|
|
|
|
updates[j][0] = leaveAlone; // yes, already on screen
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( j == nErases ) { // If not already on screen
|
|
|
|
updates[nUpdates][0] = draw;
|
|
|
|
updates[nUpdates][1] = segs[i];
|
|
|
|
nUpdates++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for ( i=0; i<nUpdates; i++ ) {
|
|
|
|
if ( updates[i][0] == draw ) {
|
|
|
|
drawSegment( pos, updates[i][1], p, segLen );
|
|
|
|
}
|
|
|
|
if (updates[i][0] == erase) {
|
|
|
|
drawSegment( pos, updates[i][1], p, segLen, TRUE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(m_prevSegments, newSegs, sizeof(char)*9);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGA7Segment::drawSegment(const TQPoint &pos, char segmentNo, TQPainter &p, int segLen, bool erase) {
|
|
|
|
TQPoint pt = pos;
|
|
|
|
int width = segLen/5;
|
|
|
|
|
|
|
|
const TQColorGroup & g = colorGroup();
|
|
|
|
TQColor lightColor,darkColor,fgColor;
|
|
|
|
if (erase) {
|
|
|
|
lightColor = backgroundColor();
|
|
|
|
darkColor = lightColor;
|
|
|
|
fgColor = lightColor;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lightColor = g.light();
|
|
|
|
darkColor = g.dark();
|
|
|
|
fgColor = g.foreground();
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LINETO(X,Y) addPoint( a, TQPoint(pt.x() + (X),pt.y() + (Y)))
|
|
|
|
#define LIGHT
|
|
|
|
#define DARK
|
|
|
|
|
|
|
|
if ( fill ) {
|
|
|
|
TQPointArray a(0);
|
|
|
|
|
|
|
|
//The following is an exact copy of the switch below.
|
|
|
|
//don't make any changes here
|
|
|
|
switch ( segmentNo ) {
|
|
|
|
case 0 :
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
LINETO(segLen - width - 1,width);
|
|
|
|
LINETO(width,width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
|
|
pt += TQPoint(0 , 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,width);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,segLen - width/2 - 2);
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 2 :
|
|
|
|
pt += TQPoint(segLen - 1 , 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LINETO(-width,segLen - width/2 - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(-width,width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 3 :
|
|
|
|
pt += TQPoint(0 , segLen);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,-width/2);
|
|
|
|
LINETO(segLen - width - 1,-width/2);
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
if (width & 1) { // adjust for integer division error
|
|
|
|
LINETO(segLen - width - 3,width/2 + 1);
|
|
|
|
LINETO(width + 2,width/2 + 1);
|
|
|
|
} else {
|
|
|
|
LINETO(segLen - width - 1,width/2);
|
|
|
|
LINETO(width,width/2);
|
|
|
|
}
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 4 :
|
|
|
|
pt += TQPoint(0 , segLen + 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,width/2);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,segLen - width - 2);
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 5 :
|
|
|
|
pt += TQPoint(segLen - 1 , segLen + 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LINETO(-width,segLen - width - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(-width,width/2);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 6 :
|
|
|
|
pt += TQPoint(0 , segLen*2);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,-width);
|
|
|
|
LINETO(segLen - width - 1,-width);
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 7 :
|
|
|
|
if ( smallPoint ) // if smallpoint place'.' between other digits
|
|
|
|
pt += TQPoint(segLen + width/2 , segLen*2);
|
|
|
|
else
|
|
|
|
pt += TQPoint(segLen/2 , segLen*2);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 8 :
|
|
|
|
pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 9 :
|
|
|
|
pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
#if defined(QT_CHECK_RANGE)
|
|
|
|
default :
|
|
|
|
tqWarning( "FPGA7Segment::drawSegment: (%s) Internal error."
|
|
|
|
" Illegal segment id: %d\n",
|
|
|
|
name( "unnamed" ), segmentNo );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
// End exact copy
|
|
|
|
p.setPen( fgColor );
|
|
|
|
p.setBrush( fgColor );
|
|
|
|
p.drawPolygon( a );
|
|
|
|
p.setBrush( NoBrush );
|
|
|
|
|
|
|
|
pt = pos;
|
|
|
|
}
|
|
|
|
#undef LINETO
|
|
|
|
#undef LIGHT
|
|
|
|
#undef DARK
|
|
|
|
|
|
|
|
#define LINETO(X,Y) p.lineTo(TQPoint(pt.x() + (X),pt.y() + (Y)))
|
|
|
|
#define LIGHT p.setPen(lightColor)
|
|
|
|
#define DARK p.setPen(darkColor)
|
|
|
|
if ( shadow ) {
|
|
|
|
switch ( segmentNo ) {
|
|
|
|
case 0 :
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
LINETO(segLen - width - 1,width);
|
|
|
|
LINETO(width,width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
|
|
pt += TQPoint(0,1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,width);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,segLen - width/2 - 2);
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 2 :
|
|
|
|
pt += TQPoint(segLen - 1 , 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LINETO(-width,segLen - width/2 - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(-width,width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 3 :
|
|
|
|
pt += TQPoint(0 , segLen);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,-width/2);
|
|
|
|
LINETO(segLen - width - 1,-width/2);
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
if (width & 1) { // adjust for integer division error
|
|
|
|
LINETO(segLen - width - 3,width/2 + 1);
|
|
|
|
LINETO(width + 2,width/2 + 1);
|
|
|
|
} else {
|
|
|
|
LINETO(segLen - width - 1,width/2);
|
|
|
|
LINETO(width,width/2);
|
|
|
|
}
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 4 :
|
|
|
|
pt += TQPoint(0 , segLen + 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,width/2);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,segLen - width - 2);
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 5 :
|
|
|
|
pt += TQPoint(segLen - 1 , segLen + 1);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,segLen - 2);
|
|
|
|
LINETO(-width,segLen - width - 2);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(-width,width/2);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 6 :
|
|
|
|
pt += TQPoint(0 , segLen*2);
|
|
|
|
p.moveTo(pt);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(width,-width);
|
|
|
|
LINETO(segLen - width - 1,-width);
|
|
|
|
LINETO(segLen - 1,0);
|
|
|
|
DARK;
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 7 :
|
|
|
|
if ( smallPoint ) // if smallpoint place'.' between other digits
|
|
|
|
pt += TQPoint(segLen + width/2 , segLen*2);
|
|
|
|
else
|
|
|
|
pt += TQPoint(segLen/2 , segLen*2);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 8 :
|
|
|
|
pt += TQPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
case 9 :
|
|
|
|
pt += TQPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
|
|
|
|
p.moveTo(pt);
|
|
|
|
DARK;
|
|
|
|
LINETO(width,0);
|
|
|
|
LINETO(width,-width);
|
|
|
|
LIGHT;
|
|
|
|
LINETO(0,-width);
|
|
|
|
LINETO(0,0);
|
|
|
|
break;
|
|
|
|
#if defined(QT_CHECK_RANGE)
|
|
|
|
default :
|
|
|
|
tqWarning( "FPGA7Segment::drawSegment: (%s) Internal error."
|
|
|
|
" Illegal segment id: %d\n",
|
|
|
|
name( "unnamed" ), segmentNo );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef LINETO
|
|
|
|
#undef LIGHT
|
|
|
|
#undef DARK
|
|
|
|
}
|
|
|
|
|
|
|
|
ImageViewerWindow::ImageViewerWindow(TQString caption, TQWidget *parent, const char *name)
|
|
|
|
: KMdiChildView(caption, parent, name)
|
|
|
|
{
|
|
|
|
TQGridLayout* layout = new TQGridLayout(this);
|
|
|
|
m_label = new TQLabel(this);
|
|
|
|
layout->addWidget(m_label, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImageViewerWindow::~ImageViewerWindow() {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
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_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(0xffffffff),
|
|
|
|
m_7segDigit2OutputValue(0xffffffff), m_7segDigit1OutputValue(0xffffffff), m_7segDigit0OutputValue(0xffffffff),
|
|
|
|
m_batchOutputFile(NULL), m_dataOutputFile(NULL),
|
|
|
|
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_connectionTimer = new TQTimer(this);
|
|
|
|
connect(m_connectionTimer, SIGNAL(timeout()), this, SLOT(finishConnectingToServer()));
|
|
|
|
|
|
|
|
// Create widgets
|
|
|
|
m_base = new FPGAViewBase(widget());
|
|
|
|
|
|
|
|
// 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->group4BitInputValueLabel->setFixedSize(LED_BASE_SIZE*2, LED_BASE_SIZE*2);
|
|
|
|
m_base->group4BitOutputValueLabel->setFixedSize(LED_BASE_SIZE*2, LED_BASE_SIZE*2);
|
|
|
|
m_base->group4BitInputValueText->setFixedSize(LED_BASE_SIZE*2, LED_BASE_SIZE*2);
|
|
|
|
m_base->group4BitOutputValueText->setFixedSize(LED_BASE_SIZE*2, LED_BASE_SIZE*2);
|
|
|
|
|
|
|
|
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->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->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->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);
|
|
|
|
|
|
|
|
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));
|
|
|
|
m_base->frameLCDDisplay->setFrameStyle(TQFrame::Box | TQFrame::Raised);
|
|
|
|
|
|
|
|
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()));
|
|
|
|
|
|
|
|
processAllGraphicsUpdates();
|
|
|
|
|
|
|
|
TQTimer::singleShot(0, this, TQT_SLOT(postInit()));
|
|
|
|
}
|
|
|
|
|
|
|
|
FPGAViewPart::~FPGAViewPart() {
|
|
|
|
// 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 label
|
|
|
|
m_base->group4BitOutputValueText->setText(TQString("0x%1").arg(m_16bitOutputValue, 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 & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED5->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED4->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED3->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED2->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED1->setState((m_8bitInputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitInputLED0->setState((m_8bitInputValue & 0x80)?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("0x%1").arg(m_8bitInputValue, 0, 16));
|
|
|
|
|
|
|
|
if (m_remoteInputModeEnabled) {
|
|
|
|
m_base->group8BitInput->setTitle(i18n("8-Bit Input Values") + " [" + i18n("Remote Input Mode") + "]");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_base->group8BitInput->setTitle(i18n("8-Bit Input Values") + " [" + i18n("Local Input Mode") + "]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED5->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED4->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED3->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED2->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED1->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
m_base->group8BitOutputLED0->setState((m_8bitOutputValue & 0x80)?KLed::On:KLed::Off);
|
|
|
|
|
|
|
|
m_base->group8BitOutputValueText->setText(TQString("0x%1").arg(m_8bitOutputValue, 0, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
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("0x%1").arg(m_16bitOutputValue, 0, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGAViewPart::processLCDOutputChanges() {
|
|
|
|
// Write m_LCDOutputValue to label
|
|
|
|
TQString topLine = m_LCDOutputValue;
|
|
|
|
TQString bottomLine = m_LCDOutputValue;
|
|
|
|
topLine.truncate(16);
|
|
|
|
bottomLine.remove(0,8);
|
|
|
|
m_base->LCDOutputLabel->setText(topLine + "\n" + bottomLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_base->ImageInputLabel->size());
|
|
|
|
}
|
|
|
|
if (!m_outputImageViewer) {
|
|
|
|
m_outputImageViewer = new ImageViewerWindow(i18n("Remote FPGA Output Image"));
|
|
|
|
mdiMainForm()->addWindow(m_outputImageViewer);
|
|
|
|
m_outputImageViewer->resize(m_base->ImageOutputLabel->size());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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() {
|
|
|
|
setUsingFixedSize(true);
|
|
|
|
connect(m_updateTimer, 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();
|
|
|
|
}
|
|
|
|
|
|
|
|
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_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE);
|
|
|
|
processLockouts();
|
|
|
|
updateDisplay();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGAViewPart::connectionStatusChangedCallback() {
|
|
|
|
processLockouts();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPtrList<TDEAction> FPGAViewPart::menuActionList() {
|
|
|
|
return m_menuActionList;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGAViewPart::batchTestRunButtonClicked() {
|
|
|
|
m_commHandlerState = 0;
|
|
|
|
m_commHandlerMode = 1;
|
|
|
|
m_batchUsing16Bit = m_base->batchTest16BitCheckBox->isChecked();
|
|
|
|
processLockouts();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPGAViewPart::dataProcessingRunButtonClicked() {
|
|
|
|
m_commHandlerState = 0;
|
|
|
|
m_commHandlerMode = 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] = m_16bitInputValue&0xff;
|
|
|
|
data[12] = '\r';
|
|
|
|
m_socket->writeBlock(data, 13);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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_base->LCDOutputLabel->setText(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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; \
|
|
|
|
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_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE); \
|
|
|
|
return;
|
|
|
|
|
|
|
|
void FPGAViewPart::updateDisplay() {
|
|
|
|
m_updateTimer->stop();
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
// Send request for all output states
|
|
|
|
m_socket->writeLine("L\r");
|
|
|
|
m_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE);
|
|
|
|
|
|
|
|
m_commHandlerState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// Get all data
|
|
|
|
if (m_socket->bytesAvailable() >= 41) {
|
|
|
|
// 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_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE);
|
|
|
|
|
|
|
|
m_commHandlerState = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!m_updateTimer->isActive()) {
|
|
|
|
UPDATEDISPLAY_TIMEOUT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
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)) {
|
|
|
|
m_batchCurrentValueIndex = 0;
|
|
|
|
m_commHandlerState = 1;
|
|
|
|
}
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
sendInputStatesToRemoteFPGA();
|
|
|
|
|
|
|
|
// Send request for all output states
|
|
|
|
m_socket->writeLine("L\r");
|
|
|
|
m_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE);
|
|
|
|
m_commHandlerState = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_commHandlerState == 2) {
|
|
|
|
// Get all data
|
|
|
|
if (m_socket->bytesAvailable() >= 41) {
|
|
|
|
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_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE);
|
|
|
|
|
|
|
|
m_commHandlerState = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!m_updateTimer->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_base->batchTestStatusLabel->setText(i18n("Reading input data") + "...");
|
|
|
|
m_batchInputValueList.clear();
|
|
|
|
TQFile file(m_base->batchTestInputFile->url());
|
|
|
|
if (file.open(IO_ReadOnly)) {
|
|
|
|
// Is it an image?
|
|
|
|
m_dataIsImage = m_dataInputImage.load(m_base->batchTestInputFile->url());
|
|
|
|
|
|
|
|
if ((file.size() <= 16384) || ((m_dataIsImage) && ((m_dataInputImage.height()*m_dataInputImage.width()) <= 16384))) {
|
|
|
|
m_base->dataProcessingProgressBar->setTotalSteps(0);
|
|
|
|
m_base->dataProcessingProgressBar->setProgress(0);
|
|
|
|
|
|
|
|
m_dataOutputFile = new TQFile(m_base->batchTestOutputFile->url());
|
|
|
|
if (m_dataOutputFile->open(IO_ReadWrite)) {
|
|
|
|
if (!m_dataIsImage) {
|
|
|
|
m_dataByteArray = file.readAll();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Show image in GUI
|
|
|
|
TQPixmap inputImagePixmap(m_dataInputImage);
|
|
|
|
m_base->ImageInputLabel->setPixmap(inputImagePixmap);
|
|
|
|
m_inputImageViewer->setPixmap(inputImagePixmap);
|
|
|
|
// Populate m_dataByteArray with image data
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
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++) {
|
|
|
|
m_dataByteArray[(y*imageWidth)+x] = tqGray(m_dataInputImage.pixel(x,y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_base->dataProcessingStatusLabel->setText(i18n("Transmitting data to FPGA") + "...");
|
|
|
|
|
|
|
|
// Transmit m_dataByteArray to FPGA
|
|
|
|
m_socket->writeLine("M\r");
|
|
|
|
int len = m_dataByteArray.size();
|
|
|
|
if (len >= 16384) {
|
|
|
|
len = 16384;
|
|
|
|
}
|
|
|
|
TQByteArray dataToSend(16384*2);
|
|
|
|
for (i=0; i<(len*2); i++) {
|
|
|
|
dataToSend[(i*2)+0] = m_dataByteArray[i];
|
|
|
|
dataToSend[(i+2)+1] = '\r';
|
|
|
|
}
|
|
|
|
m_socket->writeBlock(dataToSend, len*2);
|
|
|
|
|
|
|
|
m_base->dataProcessingStatusLabel->setText(i18n("Waiting for data from FPGA") + "...");
|
|
|
|
|
|
|
|
m_updateTimer->start(FPGA_DATA_PROCESSING_TIMEOUT_MS, FALSE);
|
|
|
|
|
|
|
|
m_batchCurrentValueIndex = 0;
|
|
|
|
m_commHandlerState = 1;
|
|
|
|
}
|
|
|
|
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() >= 16384) {
|
|
|
|
TQByteArray recData(16384);
|
|
|
|
m_socket->readBlock(recData.data(), recData.size());
|
|
|
|
|
|
|
|
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;
|
|
|
|
int imageWidth = outputImage.width();
|
|
|
|
m_dataByteArray.resize(outputImage.height()*imageWidth);
|
|
|
|
for (y=0; y<outputImage.height(); y++) {
|
|
|
|
for (x=0; x<outputImage.width(); x++) {
|
|
|
|
outputImage.setPixel(x, y, recData[(y*imageWidth)+x]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQPixmap outputImagePixmap(outputImage);
|
|
|
|
m_base->ImageOutputLabel->setPixmap(outputImagePixmap);
|
|
|
|
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->batchTestOutputFile->url() + ".vrf");
|
|
|
|
if (verificationFile.open(IO_ReadWrite)) {
|
|
|
|
TQCString datastring = writtenMD5.hexDigest();
|
|
|
|
datastring.prepend("md5=");
|
|
|
|
verificationFile.writeBlock(datastring);
|
|
|
|
datastring = (TQString("datetime=").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();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!m_updateTimer->isActive()) {
|
|
|
|
m_dataOutputFile->flush();
|
|
|
|
m_dataOutputFile->close();
|
|
|
|
delete m_dataOutputFile;
|
|
|
|
m_dataOutputFile = NULL;
|
|
|
|
m_base->dataProcessingProgressBar->reset();
|
|
|
|
m_commHandlerMode = 0;
|
|
|
|
m_commHandlerState = 0;
|
|
|
|
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"
|