Leigh et al.1
Supplemental Information for M3: Maskless Microscope-based Micropatterning with Dry Film Photoresist
Part I: Programming of the microscope stage
The control of the microscope stage is typically done by sending commands via the serial port. The programming will depend on the particular type/model used.
For example, for the Optiscan II Prior Stage (Prior Scientific, Rockland, MD) used here, the commands for control through the serial port can be found in Section 5.5. of the manual:
- Stage Control via HyperTerminal
For very simple manual control of the stage, e.g. drawing straight lines with certain speed, spaced some distance apart, one can use command-line entry via the HyperTerminal. Sending commands through the HyperTerminal is very straightforward, and for this particular stage the process is described in Appendix C, section 9.3 of the manual (link above).
Given below are two very simple examples of drawing parallel lines at specified spacing with specified exposure time (stage velocity). The commands are specific for the Optiscan II Prior Stage, but similar code can be used to generate simple patterns easily.
In the first example implementation, 3 lines are drawn with a velocity of 800m/s, which is 10% of the maximum speed for the stage used here (SMS sets the speed at % allowed). The lines are each 1mm long and spaced 2mm apart. The GR command allows relative setting of coordinates (x, y) in micrometers.
SMS 10
GR 0 1000
GR 2000 0
GR 0 -1000
GR 2000 0
GR 0 1000
In an alternative example implementation below, 3 lines spaced 1mm apart are drawn to span the extent of the glass coverslide, and line width is controlled by operating the stage at a user-chosen fixed speed (set by the VS command at 500, 700 and 1500m/s). Transition between the lines is with manual interrupts (i <Enter>).
VS 500 0
i <Enter>
GR 0 1000
VS -700 0
i <Enter>
GR 0 1000
VS 1500 0
i <Enter>
- GUI-enabled Automated Control
For more user-friendly and/or advanced programming, different programming environments can be utilized to translate user’s input into stage-specific commands, possibly via a graphical user interface (GUI). In our case, this environment is Qt by Nokia ( a cross-platform application and user-interface framework that allows code portability between desktop, mobile and embedded systems. A free Qt compiler can be downloaded here: (select ‘LGPL’, then select operating system). This particular programming environment uses C++. Attached below is a snapshot of the user interface designed in Qt for stage control. Visible in the background are the project source files.
Provided below is the code from the two main source files:
acs_m3.cpp – generates user interface, defines event functions
qacs.cpp – translates user’s commands into serial port commands for the particular stage
/*******************************************************************************
** Source File:asc_m3.cpp (Qt Defined - DO NOT REMOVE) **
** Project:ASC_M3.pro **
** Author:Aashay Tattu **
** Experiment:Microscope based Maskless Micropatterening (M3) **
** Lab:Cardiac Cell Engineering Lab **
** PI:Dr. Emilia Entcheva **
** Department:Biomedical Engineering, SUNY Stony Brook **
** **
** Copyright:CANNOT BE UNDER COPYRIGHT (SEE BELOW) **
** Licence:GNU General Public License 3.1 **
** License Holder:Nokia Inc. (Qt) **
** **
** Created:2009-Mar-16 **
** Last Modified:2009-Mar-16 **
** Last Modified by:Aashay Tattu **
** **
** Purpose:Define event functions of class ASC_M3. **
*******************************************************************************/
#include "asc_m3.h"
#include <QPainter>
ASC_M3::ASC_M3(QWidget *parent)
: QMainWindow(parent), ui(new Ui::ASC_M3Class)
{
ui->setupUi(this);
aSC_obj.set_mw(ui);
completeMenu();
QObject::connect(&aSC_obj, SIGNAL(sis_warnDlg_sig(int)), this, SLOT(sis_warnDlg_slot(int)), Qt::DirectConnection);
}
ASC_M3::~ASC_M3()
{
delete ui;
}
void ASC_M3::customEvent_install()
{
ui->tools_settings->installEventFilter(this);
ui->tools_settings_COM->installEventFilter(this);
ui->tools_settings_general->installEventFilter(this);
ui->tools_settings_pattern->installEventFilter(this);
}
void ASC_M3::enterEvent(QEvent* evt)
{
this->setWindowOpacity(1.0);
}
void ASC_M3::leaveEvent(QEvent* evt)
{
this->setWindowOpacity(0.7);
}
bool ASC_M3::eventFilter(QObject* watched, QEvent* evt)
{
if (watched == ui->tools_settings)
{
if (evt->type() == QEvent::MouseMove)
this->setWindowOpacity(1.0);
}
else
{
//For unhandled cases, send event to parent class
return QMainWindow::eventFilter(watched, evt);
}
return false;
}
void ASC_M3::on_sis_clicked()
{
int ret;
ret = sis_warnDlg_slot(1);
if (ret == QMessageBox::Cancel)
{
return;
}
QString* retList = new QString;
ret = aSC_obj.COM_out("SIS\r", retList);
if (ret == -1)
{
// COM port failed to open
messageDisplay (COM_CONN_FAIL);
return;
}
}
void ASC_M3::on_Setup_COM_clicked()
{
bool ok;// type conversion success check
char chCOM[8] = "COM\0";// chCOM = location of COM port
errCode ret;// return form QaSC::set_COM() indicating operation success
int loc = ui->COM_loc->text().toInt(&ok, 10);
int mesRet;
//Check if type conversion was successful
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay (TYPE_CONV);
ui->COM_loc->selectAll();
return;
}
//Warn user of button's operations
mesRet = messageDisplay("This button will open the COM port\n"
"and perform initial calibration\n"
"including MOVING THE STAGE TO POSITION Zero and back.\n"
"This command may take up to 30s to complete...\n\n"
"Do you wish to continue?",
"Warning!", QMessageBox::Yes|QMessageBox::No, QMessageBox::No, QMessageBox::Warning);
if (mesRet == QMessageBox::No)
return;
//Create COM port location string
QByteArray COM_BA = ui->COM_loc->text().toAscii();
strcat(chCOM, COM_BA.data());
//Test location and assign if successful
ret = aSC_obj.set_COM(chCOM);
if (ret == COM_CONN_FAIL)
{
messageDisplay(COM_CONN_FAIL);
// ui->COM_loc->setText(""); //optional reset of COM port location textbox
return;
}
else
{
messageDisplay ("COM port successfully openned!\n",
"COM connection Success!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Information);
ui->Setup_COM->setEnabled(false);
aSC_obj.stageSettings.COM_port_int = loc;
}
}
int ASC_M3::sis_warnDlg_slot(int stat)
{
if (stat == 0)// Cancel not Allowed - used for initial positioning
{
return messageDisplay ("WARNING!\n"
"SIS command invoked.\n"
"Stage will now be moved to True Mechanical Zero postion.\n\n"
"ENSURE THAT THE OBJECTIVES WHEEL SET LOWERED ALL THE WAY!\n\n"
"This command cannot be cancelled.",
"WARNING!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Warning);
}
else if (stat == 1)// Cancel Allowed
{
return messageDisplay ("WARNING!\n"
"SIS command invoked.\n"
"Stage will now be moved to True Mechanical Zero postion.\n\n"
"ENSURE THAT THE OBJECTIVES WHEEL SET LOWERED ALL THE WAY!\n\n",
"WARNING!",
QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel, QMessageBox::Warning);
}
else //Undocumented exit -- should not occur
return -1;
}
void ASC_M3::on_gotoXY_button_clicked()
{
int xx, yy;
bool ok = false;
xx = ui->xVal->text().toInt(&ok, 10);
//Check if type conversion was successful
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay(TYPE_CONV);
ui->xVal->selectAll();
return;
}
yy = ui->yVal->text().toInt(&ok, 10);
//Check if type conversion was successful
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay(TYPE_CONV);
ui->yVal->selectAll();
return;
}
int code;
if (ui->radioTru->isChecked())
code = 0;
else if (ui->radioMark->isChecked())
code = 1;
else if (ui->radioCurr->isChecked())
code = 2;
aSC_obj.gotoXY (xx, yy, code);
}
void ASC_M3::completeMenu()
{
QObject::connect(ui->file_quit, SIGNAL(triggered()), this, SLOT(file_Quit()));
QObject::connect(ui->tools_settings_general, SIGNAL(triggered()), this, SLOT(tools_settings_general()));
QObject::connect(ui->tools_settings_COM, SIGNAL(triggered()), this, SLOT(tools_settings_COM()));
QObject::connect(ui->tools_settings_pattern, SIGNAL(triggered()), this, SLOT(tools_settings_pattern()));
QObject::connect(ui->pattern_points, SIGNAL(triggered()), this, SLOT(patternPoints()));
QObject::connect(ui->pattern_image, SIGNAL(triggered()), this, SLOT(patternImage()));
QObject::connect(ui->pattern_Eqn, SIGNAL(triggered()), this, SLOT(patternEqn()));
QObject::connect(ui->interpreted_Image, SIGNAL(triggered()), this, SLOT(interpretedImage()));
QObject::connect(ui->gotoxyBox, SIGNAL(mouseMoveEvent(QMouseEvent*)), this, SLOT(mouseMoveEvent(QMouseEvent*)));
}
void ASC_M3::file_Quit()
{
//Confirm
//Stop All Stage Movement
//Disconnect from COM port
aSC_obj.COM_disconnect();
//Destruct ui
this->close();
}
void ASC_M3::tools_settings_general()
{
sd.display(0, &aSC_obj.COM_settings, &aSC_obj.stageSettings, &aSC_obj.patternSettings);
}
void ASC_M3::tools_settings_COM()
{
sd.display(1, &aSC_obj.COM_settings, &aSC_obj.stageSettings, &aSC_obj.patternSettings);
}
void ASC_M3::tools_settings_pattern()
{
sd.display(2, &aSC_obj.COM_settings, &aSC_obj.stageSettings, &aSC_obj.patternSettings);
}
int ASC_M3::messageDisplay(errCode err)
{
char mesStr[512] = "\0";
char title[64] = "\0";
int buttons;
QMessageBox::StandardButton defButton;
QMessageBox::Icon icon;
if ((err = NO_ERR) || (err = EMPTY_IN_STR))
{
return 0;
}
else if (err == COM_CONN_FAIL)
{
strcpy (mesStr, "COM port failed to open!\nRecheck location and connection.");
strcpy (title, "COM connection Error!");
buttons = QMessageBox::Ok;
defButton = QMessageBox::Ok;
icon = QMessageBox::Critical;
}
else if (err == TYPE_CONV)
{
strcpy (mesStr, "Value in Y coordinate box is NOT an integer!\n");
strcpy (title, "Type Conversion Error!");
buttons = QMessageBox::Ok;
defButton = QMessageBox::Ok;
icon = QMessageBox::Critical;
}
else
{
return -1;
}
QMessageBox msgBox;
msgBox.setIcon(icon);
msgBox.setText (mesStr);
msgBox.setStandardButtons((QMessageBox::StandardButton)buttons);
msgBox.setDefaultButton(defButton);
msgBox.setFixedSize(msgBox.size());
msgBox.setWindowTitle(title);
return msgBox.exec();
}
int ASC_M3::messageDisplay(const char* mesStr, const char* title, int buttons, QMessageBox::StandardButton defButton, QMessageBox::Icon icon)
{
QMessageBox msgBox;
msgBox.setIcon(icon);
msgBox.setText (mesStr);
msgBox.setStandardButtons((QMessageBox::StandardButton)buttons);
msgBox.setDefaultButton(defButton);
msgBox.setFixedSize(msgBox.size());
msgBox.setWindowTitle(title);
return msgBox.exec();
}
void ASC_M3::on_COM_loc_lostFocus()
{
bool ok = false;
int loc = ui->COM_loc->text().toInt(&ok, 10);
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay (TYPE_CONV);
ui->COM_loc->selectAll();
return;
}
if (loc != aSC_obj.stageSettings.COM_port_int)
{
ui->Setup_COM->setEnabled(true);
}
}
void ASC_M3::on_kill_clicked()
{
aSC_obj.kill();
}
void ASC_M3::on_COM_conn_clicked()
{
if (aSC_obj.COM_connect() != NO_ERR)
messageDisplay ("COM connection unsuccessful\n\n"
"Verify that settings are correct.", "Connection Error!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Critical);
else
{
ui->COM_conn->setEnabled(false);
ui->COM_disconn->setEnabled(true);
}
}
void ASC_M3::on_COM_disconn_clicked()
{
if (aSC_obj.COM_disconnect() != NO_ERR)
messageDisplay ("COM disconnection unsuccessful\n\n"
"Unknown Error", "Disconnection Error!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Critical);
else
{
ui->COM_disconn->setEnabled(false);
ui->COM_conn->setEnabled(true);
}
}
void ASC_M3::patternPoints()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open csv file with list of points"), tr(""),
tr("Text Files (*.txt);;Comma Separated Value File (*.csv);;All Files (*.*)"), 0, QFileDialog::DontUseNativeDialog);
if (fileName.isNull())
return;
QFile ptsFile(fileName);
QStringList* pts = new QStringList;
QString line;
if (!ptsFile.open(QIODevice::ReadOnly|QIODevice::Text))
{
messageDisplay("Could not open file for reading!\n"
"Please verify that file exists.", "File not opened",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Warning);
return;
}
else
{
QTextStream t(&ptsFile);
while (!t.atEnd())
{
//Read a line
line = t.readLine();
//CHECK IF LINE BEING READ IS A VALID LINE
//Append to pts
pts->append(line);
}
// Close File
ptsFile.close();
// FOR NOW GO STRAIGHT TO QaSC::points()
//aSC_obj.pointsP(pts);
aSC_obj.pointsP(pts);
}
}
void ASC_M3::patternImage()
{
ASC_M3::messageDisplay("Experimental Feature!", "Experimental Feature!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Critical);
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Image Viewer"),
tr("Cannot load %1.").arg(fileName));
return;
}
aSC_obj.ptsCount(image);
aSC_obj.pointsP_test();
}
}
void ASC_M3::patternEqn()
{
eqnDlg.display();
}
void ASC_M3::interpretedImage()
{
// if (ptsData == NULL)
//delete ptsData;
// ptsData = new ptsData_struct;
// fstream fin;
// fin.open("D:\\All My Stuff\\CCEL\\C++\\M3\\QProject\\ASC_M3\\Patterns\\BigspiCirc_Pattern.dat", ios::in);
// fin.read(reinterpret_cast<char*>(ptsData), sizeof(ptsData_struct));
// fin.close();
// aSC_obj.pointsP_test();
}
void ASC_M3::on_markZero_clicked()
{
QString *str = new QString;
errCode ret;
ret = aSC_obj.COM_out("PS\r", str);
QStringList strLst;
strLst = str->split('\r', QString::SkipEmptyParts);
str->clear();
str->append(strLst.value(0));
strLst.clear();
strLst = str->split(',', QString::SkipEmptyParts);
str->clear();
bool *ok = new bool;
qlonglong marker;
str->append(strLst.value(0));
marker = str->toLongLong(ok, 10);
if (!ok)
{
messageDisplay(COM_UNK_READ);
return;
}
ui->xPos->setText(*str);
aSC_obj.stageSettings.xMark = marker;
str->clear();
str->append(strLst.value(1));
marker = str->toLongLong(ok, 10);
if (!ok)
{
messageDisplay(COM_UNK_READ);
return;
}
ui->yPos->setText(*str);
aSC_obj.stageSettings.yMark = marker;
delete str;
}
void ASC_M3::on_queryPos_clicked()
{
QString *str = new QString;
errCode ret;
ret = aSC_obj.COM_out("PS\r", str);
QStringList strLst;
strLst = str->split('\r', QString::SkipEmptyParts);
str->clear();
str->append(strLst.value(0));
strLst.clear();
strLst = str->split(',', QString::SkipEmptyParts);
str->clear();
bool *ok = new bool;
qlonglong marker;
str->append(strLst.value(0));
marker = str->toLongLong(ok, 10);
if (!ok)
{
messageDisplay(COM_UNK_READ);
return;
}
ui->xPos->setText(*str);
str->clear();
str->append(strLst.value(1));
marker = str->toLongLong(ok, 10);
if (!ok)
{
messageDisplay(COM_UNK_READ);
return;
}
marker *= -1;
str->number(marker, 10);
ui->yPos->setText(*str);
delete str;
// delete str2;
}
void ASC_M3::on_COM_loc_returnPressed()
{
on_Setup_COM_clicked();
}
void ASC_M3::on_xVal_returnPressed()
{
on_gotoXY_button_clicked();
}
void ASC_M3::on_yVal_returnPressed()
{
on_gotoXY_button_clicked();
}
void ASC_M3::on_Setup_uScope_clicked()
{
bool ok;// type conversion success check
char chCOM[8] = "COM\0";// chCOM = location of COM port
errCode ret;// return form QaSC::set_COM() indicating operation success
int loc = ui->uScope_COM_loc->text().toInt(&ok, 10);
int mesRet;
//Check if type conversion was successful
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay (TYPE_CONV);
ui->uScope_COM_loc->selectAll();
return;
}
//Warn user of button's operations
mesRet = messageDisplay("This button will open the COM port\n"
"and perform initial calibration\n"
"including MOVING THE FILTER CUBES TO POSITION ONE and back.\n"
"This command may take up to 30s to complete...\n\n"
"Do you wish to continue?",
"Warning!", QMessageBox::Yes|QMessageBox::No, QMessageBox::No, QMessageBox::Warning);
if (mesRet == QMessageBox::No)
return;
//Create COM port location string
QByteArray COM_BA = ui->uScope_COM_loc->text().toAscii();
strcat(chCOM, COM_BA.data());
//Test location and assign if successful
ret = aSC_obj.uScope_obj.set_COM(chCOM);
if (ret == COM_CONN_FAIL)
{
messageDisplay(COM_CONN_FAIL);
// ui->COM_loc->setText(""); //optional reset of COM port location textbox
return;
}
else
{
messageDisplay ("COM port successfully openned!\n",
"COM connection Success!",
QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Information);
ui->Setup_uScope->setEnabled(false);
aSC_obj.uScope_obj.COM_int = loc;
}
}
void ASC_M3::on_uScope_COM_loc_lostFocus()
{
bool ok = false;
int loc = ui->uScope_COM_loc->text().toInt(&ok, 10);
if (!ok)
{
// Conversion to int failed; text is not int; display warning
messageDisplay (TYPE_CONV);
ui->uScope_COM_loc->selectAll();
return;
}
if (loc != aSC_obj.uScope_obj.COM_int)
{
ui->Setup_uScope->setEnabled(true);
}
}
void ASC_M3::on_uScope_COM_loc_returnPressed()
{
on_Setup_uScope_clicked();
}
/*******************************************************************************
** Source File:qasc.cpp (User Defined) **
** Project:ASC_M3.pro **
** Author:Aashay Tattu **
** Experiment:Microscope based Maskless Micropatterening (M3) **
** Lab:Cardiac Cell Engineering Lab **
** PI:Dr. Emilia Entcheva **
** Department:Bio-Medical Engineering, SUNY Stony Brook **
** **
** Copyright:CANNOT BE UNDER COPYRIGHT (SEE BELOW) **
** Licence:GNU General Public License 3.1 **
** License Holder:Nokia Inc. (Qt) **
** **
** Created:2009-Mar-16 **
** Last Modified:2009-Apr-06 **
** Last Modified by:Aashay Tattu **
** **
** Purpose:Function definitions for class QaSC (Qt version) **
** **
*******************************************************************************/
// ------Begin preprocessor directors------
#include <qasc.h>
#include <ui_asc_m3.h>
#include <fstream>
#include <string>
#include <limits>
#include <math.h>
#include <windows.h>
#include <QMessageBox>
#include <QTimer>
// ------End preprocessor directives------
// ------Begin Function Definitions------
// Function aSC: User-defined constructor
// Arguments: NONE
// Return: NONE
QaSC::QaSC()
{
COM_port = new char[6]; // initialize COM port location invalid location
strcpy(COM_port, "COM\0\0\0");
//Initialise var COM_settings
COM_settings.BaudRate = BAUD9600;
COM_settings.DataBits = DATA_8;
COM_settings.FlowControl = FLOW_HARDWARE;
COM_settings.Parity = PAR_NONE;
COM_settings.StopBits = STOP_1;
COM_settings.Timeout_Millisec = 5000;
// COM_settings.Timeout_Sec = 5;// Set timeout = 5.00 s
//Apply settings to COM port object
COM_obj.setPortName(COM_port);
COM_obj.setBaudRate(COM_settings.BaudRate);
COM_obj.setDataBits(COM_settings.DataBits);
COM_obj.setStopBits(COM_settings.StopBits);
COM_obj.setParity(COM_settings.Parity);
COM_obj.setFlowControl(COM_settings.FlowControl);
COM_obj.setTimeout(COM_settings.Timeout_Millisec);
//Apply the initial stage settings
stageSettings.COM_port_int = -1;
stageSettings.lastERR_COM = E_NO_ERROR;
stageSettings.xVM = 75;
stageSettings.yVM = 75;
stageSettings.xAM = 75;
stageSettings.yAM = 75;
stageSettings.ss = 100;
stageSettings.xDir = 1;
stageSettings.yDir = -1;
stageSettings.xMark = 0;
stageSettings.yMark = 0;
patternSettings.xStart = 0;
patternSettings.xMax = 0;
patternSettings.yStart = 0;
patternSettings.yMax = 0;
patternSettings.vOpt = 0;// = 0.19X 8mm/s = 1.52mm/s
stageSet = false;
stageConn = false;
mw = NULL; //initialize main window handle to NULL
}
// Function set_mw: sets the handle to the main window
// Arguments: Ui::ASC_M3Class* to the handle of the main window
// Return: NONE
// Note: Function is called during constructor of class asc_m3
void QaSC::set_mw(Ui::ASC_M3Class* mwHandle)
{
mw = mwHandle;
}
// Function set_COM: tests and sets COM_port to char[] with com port name
// Arguments: char* to location of COM port
// Return: errCode for operation success/failure
// Note: Function is called during constructor of class asc_m3
errCode QaSC::set_COM(char* loc)
{
if(COM_obj.isOpen())
COM_obj.close();
COM_obj.setPortName(loc);
//Attempt to open COM port for: Read+Write+textmode+truncate@begin+unbuffered
if (!COM_obj.open(QIODevice::ReadWrite|QIODevice::Text|QIODevice::Truncate|QIODevice::Unbuffered))
return COM_CONN_FAIL;
//Reset stored COM port name
delete COM_port;
COM_port = new char[sizeof(loc)];
strcpy(COM_port, loc);
return setupStage();
}
// Function COM_out: sends command string to COM
// Arguments: char* to command string to be sent
// Return:errCode for errors
errCode QaSC::COM_out(const char* cmd)
{
QString* str = new QString;
qint64 ret = 0;
if (!COM_obj.isOpen())
return COM_CONN_FAIL;
ret = COM_obj.write(cmd);
if (!ret)
return COM_CONN_FAIL;
COM_in(str);
return NO_ERR;
}
// Function COM_out: sends command string to COM
// Arguments: char* to command string to be sent
//QStringList* for the return
/// Return:errCode for errors
errCode QaSC::COM_out(const char* cmd, QString* readIn)
{
qint64 ret = 0;
if (!COM_obj.isOpen())
return COM_CONN_FAIL;
ret = COM_obj.write(cmd);
if (!ret)
return COM_CONN_FAIL;
errCode ret2 = COM_in(readIn);
return ret2;
}
// Function COM_in: reads COM input buffer
// Arguments: char* to store input string
// Return: errCode error code
errCode QaSC::COM_in(QString* readIn)
{
if (!COM_obj.isOpen())
return COM_CONN_FAIL;
//Max stream size
int streamSize = 256;
char *inStr = new char[streamSize];
//Erase readIn if not empty
if (!readIn->isEmpty())
readIn->clear();
//Sleep(COM_settings.Timeout_Millisec);
int howMany;
memset(inStr, 0, streamSize);
char *tmp = new char[streamSize];
memset(tmp, 0, streamSize);
//Using QTimer object to control for timeout event
QTimer timer;
timer.setInterval(COM_settings.Timeout_Millisec);
timer.setSingleShot(true);
timer.start();
do
{
howMany = COM_obj.bytesAvailable();
}while (howMany == 0 & timer.isActive());
if (!timer.isActive())
{
return COM_TIMEOUT;
}
COM_obj.readLine(inStr, streamSize);
readIn->append(inStr);
if (inStr[0] == 0)
return EMPTY_IN_STR;
delete inStr;
return NO_ERR;
}
// Function COM_ignore: ignores ALL COM input buffer
// Arguments: char* to store input string
// Return: errCode error code
errCode QaSC::COM_ignore()
{
if (!COM_obj.isOpen())
return COM_CONN_FAIL;
if (COM_obj.bytesAvailable() == 0)
return EMPTY_IN_STR;
while (COM_obj.bytesAvailable() != 0)
{
COM_obj.readAll();
}
return NO_ERR;
}
// Function COM_ignore: overloaded; ignores n characters of the COM input buffer
// Arguments: int to number of characters to ignore
// Return: errCode error code
errCode QaSC::COM_ignore(int numIgn)
{
if (!COM_obj.isOpen())
return COM_CONN_FAIL;
if (COM_obj.bytesAvailable() == 0)
return EMPTY_IN_STR;
//Max stream size
int streamSize = 256;
char *inStr = new char[streamSize];
while (COM_obj.bytesAvailable() != 0)
{
if (COM_obj.bytesAvailable() != 0)
{
memset(inStr, 0, streamSize);
COM_obj.readLine(inStr, streamSize);
}
}
delete inStr;
return NO_ERR;
}
// Function setupStage: Applies initial settings to stage
// Arguments: NONE
// Return: int for success of operation
errCode QaSC::setupStage()
{
int ret = 0;
QStringList *retList = NULL;
retList = new QStringList;
//ADD CHECK FOR COM CONNECTED - part of COM_out
//Set Baud rate
ret += COM_out ("BAUD,9600\r");
//Set stage scaling Factor to 100 (steps are now counted in microns)
ret += COM_out ("SS,100\r");
stageSettings.ss = 100;
//Set Compatibility mode to ON
ret += COM_out ("COMP,1\r");
//Set error reporting to machine readable
ret += COM_out ("ERROR,0\r");
//Set stage max acceleration to 75%
ret += COM_out ("SAS,75\r");
//Set stage max speed to 75%
ret += COM_out ("SMS,75\r");
//Set Abs. Zero
//(Cannot be cancelled since otherwise ASC_M3 has no idea where the stage is)
emit sis_warnDlg_sig(0);
ret += sis();
//FIND DIMENSIONS AND POSITION OF SLIDE WITH PHOTORESIST
//Return ret // NEEDS TO BE CHANGED FOR errCode
if (!ret)
return COM_CONN_FAIL;
else
{
stageConn = true;
return NO_ERR;
}
}
// Function sis: sends stage to absolute Zero position and sets the
// Arguments: int X, Y - (x,y) position in microns
// Return: errCode error code
errCode QaSC::sis()
{
int ret = 0;
char str[32];
ulong tms = COM_settings.Timeout_Millisec;
COM_settings.Timeout_Millisec = 30000;
COM_obj.setTimeout(30000);
ret += COM_out("SAS,100\r");
ret += COM_out("SMS,100\r");
ret += COM_out("SIS\r");
COM_obj.readData(str, 32);
COM_obj.setTimeout(tms);
COM_settings.Timeout_Millisec = tms;
if (!ret)
return COM_CONN_FAIL;
stageSettings.xMark = 0;
stageSettings.yMark = 0;
return NO_ERR;
}
// Function ris: sends stage to absolute Zero position and returns to starting pos.
// Arguments: int X, Y - (x,y) position in microns
// Return: errCode error code
errCode QaSC::ris()
{
int ret = 0;
char str[32] = "\0";
QByteArray readTemp;
ulong tms = COM_settings.Timeout_Millisec;
COM_obj.setTimeout(30000);
ret += COM_out("SAS,100\r");
ret += COM_out("SMS,100\r");