diff --git a/clients/tde/src/part/fpgaview/layout.ui b/clients/tde/src/part/fpgaview/layout.ui index 966e640..8fa3afe 100644 --- a/clients/tde/src/part/fpgaview/layout.ui +++ b/clients/tde/src/part/fpgaview/layout.ui @@ -571,7 +571,7 @@ batchTestOutputFile - 25 + 17 *.txt|Text Files (*.txt) diff --git a/clients/tde/src/part/fpgaview/part.cpp b/clients/tde/src/part/fpgaview/part.cpp index e97272f..769a7f9 100644 --- a/clients/tde/src/part/fpgaview/part.cpp +++ b/clients/tde/src/part/fpgaview/part.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include //encodeName() #include //postInit() hack #include @@ -39,6 +40,9 @@ #include #include #include +#include +#include +#include #include //access() #include @@ -559,7 +563,8 @@ K_EXPORT_COMPONENT_FACTORY(libremotelab_fpgaviewer, RemoteLab::Factory) FPGAViewPart::FPGAViewPart(TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const TQStringList&) : RemoteInstrumentPart( parent, name ), m_socket(0), m_base(0), connToServerConnecting(false), connToServerState(-1), connToServerTimeoutTimer(NULL), m_interfaceMode(BasicInterfaceMode), m_commHandlerState(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_16bitInputValue(0), m_16bitOutputValue(0), m_7segDigit3OutputValue(0xffffffff), m_7segDigit2OutputValue(0xffffffff), m_7segDigit1OutputValue(0xffffffff), m_7segDigit0OutputValue(0xffffffff), + m_batchOutputFile(NULL) { // Initialize mutex m_connectionMutex = new TQMutex(false); @@ -686,6 +691,8 @@ FPGAViewPart::FPGAViewPart(TQWidget *parentWidget, const char *widgetName, TQObj m_base->frameLEDDisplay->setFrameStyle(TQFrame::Box | TQFrame::Raised); #endif + connect(m_base->batchTestRunButton, SIGNAL(clicked()), this, SLOT(batchTestRunButtonClicked())); + processAllGraphicsUpdates(); TQTimer::singleShot(0, this, TQT_SLOT(postInit())); @@ -854,6 +861,24 @@ void FPGAViewPart::processLockouts() { m_modeIntermediateEnabled->setChecked(false); m_modeAdvancedEnabled->setChecked(true); } + + if ((m_base->batchTestInputFile->url() != "") && (m_base->batchTestOutputFile->url() != "") && (m_commHandlerMode != 1) && (m_connectionActiveAndValid == true)) { + m_base->batchTestRunButton->setEnabled(true); + m_base->batchTest16BitCheckBox->setEnabled(true); + } + else { + m_base->batchTestRunButton->setEnabled(false); + m_base->batchTest16BitCheckBox->setEnabled(false); + } + + if (m_commHandlerMode == 1) { + m_base->batchTestInputFile->setEnabled(false); + m_base->batchTestOutputFile->setEnabled(false); + } + else { + m_base->batchTestInputFile->setEnabled(true); + m_base->batchTestOutputFile->setEnabled(true); + } } void FPGAViewPart::switchToBasicMode() { @@ -1044,9 +1069,98 @@ TQPtrList FPGAViewPart::menuActionList() { return m_menuActionList; } +void FPGAViewPart::batchTestRunButtonClicked() { + m_commHandlerState = 0; + m_commHandlerMode = 1; + m_batchUsing16Bit = m_base->batchTest16BitCheckBox->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); \ } \ @@ -1060,124 +1174,163 @@ void FPGAViewPart::updateDisplay() { if (m_socket) { char data[64]; - switch (m_commHandlerState) { - case 0: - // Send current input states to remote system - 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); - - // 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: + 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_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_WriteOnly)) { + m_batchCurrentValueIndex = 0; + m_commHandlerState = 1; + } + else { + KMessageBox::error(0, i18n("Unable to open selected batch output file"), i18n("Batch Failed")); + m_commHandlerMode = 0; + m_commHandlerState = 0; + m_base->batchTestProgressBar->setProgress(0); + processLockouts(); + } + } + else { + KMessageBox::error(0, i18n("Unable to open selected batch input file"), i18n("Batch Failed")); + m_commHandlerMode = 0; + m_commHandlerState = 0; + m_base->batchTestProgressBar->setProgress(0); + processLockouts(); + } + } + else if (m_commHandlerState == 1) { + if (m_batchCurrentValueIndex >= m_batchInputValueList.count()) { + // Done! + m_commHandlerMode = 0; + m_commHandlerState = 0; + m_base->batchTestProgressBar->setProgress(0); + processLockouts(); + } + else { + 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 - // 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; + receiveInputStatesFromRemoteFPGA(); + + // Write received data to batch output file + if (m_batchUsing16Bit) { + line = TQString("%1\n").arg(m_16bitOutputValue); } else { - // Remote mode - m_remoteInputModeEnabled = true; + line = TQString("%1\n").arg(m_8bitOutputValue); } - - // 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(); + m_batchOutputFile->writeBlock(line.ascii(), line.length()); + m_base->batchTestProgressBar->setProgress(m_batchCurrentValueIndex); + m_batchCurrentValueIndex++; 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; - } + setStatusMessage(i18n("Running batch test") + "..."); m_updateTimer->start(FPGA_COMM_TIMEOUT_MS, FALSE); - m_commHandlerState = 0; + m_commHandlerState = 1; } else { if (!m_updateTimer->isActive()) { UPDATEDISPLAY_TIMEOUT + m_base->batchTestProgressBar->setProgress(0); + processLockouts(); } } - - break; + } + } + 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 + // RAJA FIXME } } else { m_commHandlerState = 0; + m_commHandlerMode = 0; } } diff --git a/clients/tde/src/part/fpgaview/part.h b/clients/tde/src/part/fpgaview/part.h index 4b9c071..e5bd8f8 100644 --- a/clients/tde/src/part/fpgaview/part.h +++ b/clients/tde/src/part/fpgaview/part.h @@ -42,6 +42,7 @@ class TraceWidget; class TQSocket; class TQTimer; class TQMutex; +class TQFile; class FPGAViewBase; class FPGALed : public KLed @@ -124,6 +125,8 @@ class Q_EXPORT FPGA7Segment : public TQFrame FPGA7SegmentPrivate *d; }; +typedef TQValueList UnsignedIntegerList; + namespace RemoteLab { class FPGAViewPart : public KParts::RemoteInstrumentPart @@ -170,6 +173,12 @@ namespace RemoteLab void process16BitOutputChanges(); void processLCDOutputChanges(); void process7SegmentLEDOutputChanges(); + + void batchTestRunButtonClicked(); + + private: + void sendInputStatesToRemoteFPGA(); + void receiveInputStatesFromRemoteFPGA(); private: TDEKerberosClientSocket* m_socket; @@ -190,6 +199,7 @@ namespace RemoteLab InterfaceMode m_interfaceMode; int m_commHandlerState; + int m_commHandlerMode; bool m_connectionActiveAndValid; unsigned char m_tickerState; bool m_remoteInputModeEnabled; @@ -204,6 +214,12 @@ namespace RemoteLab unsigned int m_7segDigit2OutputValue; unsigned int m_7segDigit1OutputValue; unsigned int m_7segDigit0OutputValue; + + UnsignedIntegerList m_batchInputValueList; + UnsignedIntegerList m_batchOutputValueList; + unsigned int m_batchCurrentValueIndex; + bool m_batchUsing16Bit; + TQFile* m_batchOutputFile; }; }