Supplemental Information for M3: Maskless Microscope-Based Micropatterning with Dry Film

Supplemental Information for M3: Maskless Microscope-Based Micropatterning with Dry Film

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:

  1. 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 800m/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 1500m/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>

  1. 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");