1442 lines
51 KiB
C#
1442 lines
51 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Threading;
|
|||
|
|
using log4net;
|
|||
|
|
|
|||
|
|
namespace TBF.BenchControl.Cameras.IdcCamera
|
|||
|
|
{
|
|||
|
|
public class Idc100
|
|||
|
|
{
|
|||
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Idc100));
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Constants
|
|||
|
|
///
|
|||
|
|
const string IdcHomeDir = Program.HomeDir; /// Contains subdirectory Images/...
|
|||
|
|
const int MesurementPeriod_Frames = 6;
|
|||
|
|
const int ParamsSize = 14;
|
|||
|
|
const int MaxMeasurementsCount = 160000; /// Enough for +/- 3,5h measurement
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Data marks identifying events
|
|||
|
|
///
|
|||
|
|
enum MARK
|
|||
|
|
{
|
|||
|
|
FALLING = 2000000000, /// Marks measurement start
|
|||
|
|
RISING = 2000000001, /// marks measurement end
|
|||
|
|
BEGIN = 2000000002, /// not used
|
|||
|
|
END = 2000000003, /// not used
|
|||
|
|
DUMMY = 2000000004
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>Version string</summary>
|
|||
|
|
public string Version { get { return cameraVersionStr; } }
|
|||
|
|
string cameraVersionStr; /// IDC100 version, valid after 'Connect'
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Private fields
|
|||
|
|
/// </summary>
|
|||
|
|
int cameraNr; /// 0-based camera number
|
|||
|
|
int comPortNr; /// COM port number
|
|||
|
|
int baudRate;
|
|||
|
|
float brightness; /// Relative brightness 0 .. 1.0f
|
|||
|
|
string imagesPath;
|
|||
|
|
Tools.IniUtil commonIni;
|
|||
|
|
|
|||
|
|
SerialLayer serial; /// Communications
|
|||
|
|
Thread workerThread;
|
|||
|
|
|
|||
|
|
struct Measurement
|
|||
|
|
{
|
|||
|
|
public uint timeStamp;
|
|||
|
|
public int angle;
|
|||
|
|
public Measurement(uint timeStamp, int angle)
|
|||
|
|
{
|
|||
|
|
this.timeStamp = timeStamp;
|
|||
|
|
this.angle = angle;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IList<Measurement> measurements; /// Raw angle measurements obtained by the camera
|
|||
|
|
|
|||
|
|
int wm_nrBegin; /// Measuremnt start mark
|
|||
|
|
uint wm_timestampBegin;
|
|||
|
|
|
|||
|
|
int wm_nrEnd; /// Measurement end mark
|
|||
|
|
uint wm_timestampEnd;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The angle difference since the start of the measurement operation (the start mark)
|
|||
|
|
/// </summary>
|
|||
|
|
public int Pulses
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (measurements.Count < 1 || wm_nrBegin >= measurements.Count) return 0;
|
|||
|
|
return measurements[measurements.Count - 1].angle - measurements[wm_nrBegin].angle;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The angle difference between the end and the start of the measurement operation
|
|||
|
|
/// </summary>
|
|||
|
|
public int TotalPulses
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (wm_nrBegin >= measurements.Count || wm_nrEnd > measurements.Count || wm_nrBegin > wm_nrEnd) return 0;
|
|||
|
|
return measurements[wm_nrEnd - 1].angle - measurements[wm_nrBegin].angle;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int m_initSpeed;
|
|||
|
|
|
|||
|
|
|
|||
|
|
IdcState _idcState;
|
|||
|
|
///
|
|||
|
|
IdcState idcState
|
|||
|
|
{
|
|||
|
|
get { return _idcState; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (value != _idcState)
|
|||
|
|
{
|
|||
|
|
_idcState = value;
|
|||
|
|
TBF.UiBridge.Bridge.OnCameraStateChanged(this,
|
|||
|
|
new TBF.UiBridge.CameraStateChangedEventArgs(cameraNr, value));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
///
|
|||
|
|
public IdcState IdcState { get { return _idcState; } }
|
|||
|
|
|
|||
|
|
|
|||
|
|
string m_errorStr; /// last camera error string
|
|||
|
|
RetVal m_lastError; /// last error (either host or camera)
|
|||
|
|
|
|||
|
|
/// On program exit the control sets these events to avoid deadlocks
|
|||
|
|
AutoResetEvent workerCommandEvent;
|
|||
|
|
AutoResetEvent workerEvent;
|
|||
|
|
|
|||
|
|
IWorkerCmd workerCmd;
|
|||
|
|
RetVal workerResponse;
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Constructor
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="name">Camera name = 'Images' subdirectory name)</param>
|
|||
|
|
/// <param name="comPortNr">Com port number 1..999</param>
|
|||
|
|
/// <param name="baudRate">Baud rate 57600 or 115200</param>
|
|||
|
|
/// <param name="brightness">Relative brightness 0..1.0f</param>
|
|||
|
|
public Idc100(string name, int cameraNr, int comPortNr, int baudRate, float brightness)
|
|||
|
|
{
|
|||
|
|
this.comPortNr = comPortNr;
|
|||
|
|
this.baudRate = baudRate;
|
|||
|
|
this.brightness = brightness;
|
|||
|
|
this.cameraNr = cameraNr;
|
|||
|
|
m_initSpeed = 0;
|
|||
|
|
|
|||
|
|
/// Read the rest of parameters from INI-files
|
|||
|
|
this.commonIni = new Tools.IniUtil(IdcHomeDir + "config\\common.ini");
|
|||
|
|
|
|||
|
|
/// Create SerialLayer instance
|
|||
|
|
imagesPath = string.Format("{0}Images\\{1}\\", IdcHomeDir, name);
|
|||
|
|
Directory.CreateDirectory(imagesPath);
|
|||
|
|
serial = new SerialLayer(cameraNr, comPortNr, baudRate, 2000, imagesPath);
|
|||
|
|
|
|||
|
|
/// Initialize the rest
|
|||
|
|
measurements = new List<Measurement>();
|
|||
|
|
|
|||
|
|
wm_nrBegin = 0;
|
|||
|
|
wm_nrEnd = 0;
|
|||
|
|
wm_timestampBegin = 0;
|
|||
|
|
wm_timestampEnd = 0;
|
|||
|
|
|
|||
|
|
m_lastError = RetVal.OK;
|
|||
|
|
|
|||
|
|
idcState = IdcState.NotConnected;
|
|||
|
|
workerCmd = null;
|
|||
|
|
workerResponse = 0;
|
|||
|
|
workerCommandEvent = new AutoResetEvent(false);
|
|||
|
|
workerEvent = new AutoResetEvent(false);
|
|||
|
|
|
|||
|
|
//ExecuteIdcIniFile();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public RetVal StartOp(IWorkerCmd workerCmd)
|
|||
|
|
{
|
|||
|
|
IdcState[] iniStates;
|
|||
|
|
IdcTransition[] sTransTbl;
|
|||
|
|
|
|||
|
|
///------------------------------------ Connection state ------------------------------------
|
|||
|
|
if (workerCmd is Command.Connect)
|
|||
|
|
{
|
|||
|
|
m_lastError = Connect((workerCmd as Command.Connect).TimeoutMs);
|
|||
|
|
return m_lastError;
|
|||
|
|
}
|
|||
|
|
else if (workerCmd is Command.Disconnect)
|
|||
|
|
{
|
|||
|
|
iniStates = new IdcState[] { IdcState.Idle, IdcState.Busy, IdcState.OpCompleted, IdcState.OpFailed };
|
|||
|
|
sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.SequenceError, IdcState.Unchanged),
|
|||
|
|
new IdcTransition(RetVal.FatalError, IdcState.Unchanged),
|
|||
|
|
new IdcTransition(RetVal.OK, IdcState.NotConnected), };
|
|||
|
|
serial.m_disconnecting = true;
|
|||
|
|
serial.UnlockLastRead(); /// Quit infinite fifo.Get() waiting for a character in read FIFO
|
|||
|
|
RetVal retv = IssueThreadCmd(workerCmd, iniStates, sTransTbl);
|
|||
|
|
|
|||
|
|
if (retv == RetVal.SequenceError)
|
|||
|
|
return m_lastError = RetVal.OK; /// Camera was not connected - OK
|
|||
|
|
else
|
|||
|
|
return m_lastError = retv;
|
|||
|
|
}
|
|||
|
|
else if (idcState == IdcState.NotConnected)
|
|||
|
|
{
|
|||
|
|
/// connection must be established for all remaining operations
|
|||
|
|
return (m_lastError = RetVal.CameraNotConnected);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
///------------------------------------ Other operations ------------------------------------
|
|||
|
|
|
|||
|
|
if (workerCmd is Command.Detect || workerCmd is Command.Measure || workerCmd is Command.Stream)
|
|||
|
|
{
|
|||
|
|
///
|
|||
|
|
/// Long lasting (start/stop) operations state transition table
|
|||
|
|
///
|
|||
|
|
iniStates = new IdcState[] { IdcState.Idle };
|
|||
|
|
sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.Busy, IdcState.Busy),
|
|||
|
|
new IdcTransition(RetVal.OpFailed, IdcState.OpFailed),
|
|||
|
|
new IdcTransition(RetVal.OK, IdcState.Busy), };
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
///
|
|||
|
|
/// Immediate operations state transition table
|
|||
|
|
///
|
|||
|
|
iniStates = new IdcState[] { IdcState.Idle };
|
|||
|
|
sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.Busy, IdcState.Busy),
|
|||
|
|
new IdcTransition(RetVal.OK, IdcState.Idle), };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_lastError = IssueThreadCmd(workerCmd, iniStates, sTransTbl);
|
|||
|
|
return m_lastError;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public RetVal StopOp()
|
|||
|
|
{
|
|||
|
|
IdcState[] iniStates = new IdcState[] { IdcState.Busy,
|
|||
|
|
IdcState.OpCompleted,
|
|||
|
|
IdcState.OpFailed };
|
|||
|
|
|
|||
|
|
IdcTransition[] sTransTbl = new IdcTransition[] { new IdcTransition(RetVal.SequenceError, IdcState.Unchanged),
|
|||
|
|
new IdcTransition(RetVal.OK, IdcState.Idle)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return m_lastError = IssueThreadCmd(new Command.StopOp(), iniStates, sTransTbl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
// Connect
|
|||
|
|
// Starts the worker thread, opens the COM-port and establishes
|
|||
|
|
// communication with the camera.
|
|||
|
|
// Returns:
|
|||
|
|
// 0 = OK
|
|||
|
|
// RetVal.SEQUENCE_ERROR ....... camera was already connected, etc
|
|||
|
|
// RetVal.INVALID_COMPORT_NR ... invalid COM-port number
|
|||
|
|
// RetVal.CANNOT_INIT_CAMERA ... when worker thread cannot be started
|
|||
|
|
// RetVal.CANNOT_OPEN_COMPORT ... cannot open COM-port
|
|||
|
|
// RetVal.CANNOT_SET_COMPORT_PARAMETERS ... cannot set comm. parameters
|
|||
|
|
// RetVal.COMM_TIMEOUT ... comm. timeout when establishing a connection
|
|||
|
|
// RetVal.UNKNNOWN_COMM_ERROR ... other less common comm. error
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
RetVal Connect(int timeoutMs)
|
|||
|
|
{
|
|||
|
|
lock (serial)
|
|||
|
|
{
|
|||
|
|
if (idcState != IdcState.NotConnected) return RetVal.SequenceError; /// Command sequence error
|
|||
|
|
if (comPortNr == 0) return RetVal.InvalidComPortNr;
|
|||
|
|
|
|||
|
|
/// Start the worker thread
|
|||
|
|
workerThread = new Thread(new ThreadStart(Worker));
|
|||
|
|
workerThread.Start();
|
|||
|
|
|
|||
|
|
if (workerEvent.WaitOne(timeoutMs))
|
|||
|
|
{
|
|||
|
|
if (workerResponse == RetVal.OK)
|
|||
|
|
{
|
|||
|
|
idcState = IdcState.Idle;
|
|||
|
|
return RetVal.OK; /// Intro part completed OK in time, thread is running OK
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return workerResponse; /// Return the code from the thread
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RetVal.CommTimeout; /// Timeout
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
///------------------------------------------------------------------------------
|
|||
|
|
/// Used to issue command to the worker thread
|
|||
|
|
/// Arguments:
|
|||
|
|
/// threadCmd ... thread command (definend in enum in Common.h)
|
|||
|
|
/// expectedStates ... = NULL ... do not check current state
|
|||
|
|
/// = {state1, state2, ..., 0} ... check if current
|
|||
|
|
/// state is one of states in the zero terminated arary
|
|||
|
|
/// stateTransitionTable= {{resp1,state1},{resp2,state2}, ... ,{RetVal.OK,defaultState}}
|
|||
|
|
/// (!!! last item must be {RetVal.OK,defaultState})
|
|||
|
|
/// Returns:
|
|||
|
|
/// workerResponse (error code in case of an error)
|
|||
|
|
///------------------------------------------------------------------------------
|
|||
|
|
RetVal IssueThreadCmd(IWorkerCmd workerCmd, IdcState[] expectedStates, IdcTransition[] stateTransitionTable)
|
|||
|
|
{
|
|||
|
|
lock (serial)
|
|||
|
|
{
|
|||
|
|
/// Check the initial state
|
|||
|
|
if (idcState == IdcState.NotConnected || expectedStates == null)
|
|||
|
|
{
|
|||
|
|
return RetVal.SequenceError; /// Camera is not connected or expexted states missing
|
|||
|
|
}
|
|||
|
|
///
|
|||
|
|
bool isInExpectedState = false;
|
|||
|
|
foreach (var expextedState in expectedStates)
|
|||
|
|
{
|
|||
|
|
if (idcState == expextedState) isInExpectedState = true;
|
|||
|
|
}
|
|||
|
|
if (!isInExpectedState)
|
|||
|
|
{
|
|||
|
|
return RetVal.SequenceError; /// Camera is not in any of the expected states
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Issue thread comand and wait for a response
|
|||
|
|
workerResponse = 0;
|
|||
|
|
this.workerCmd = workerCmd;
|
|||
|
|
workerCommandEvent.Set();
|
|||
|
|
workerEvent.WaitOne();
|
|||
|
|
|
|||
|
|
/// Change the state depending on the response
|
|||
|
|
if (stateTransitionTable != null)
|
|||
|
|
{
|
|||
|
|
foreach (var item in stateTransitionTable)
|
|||
|
|
{
|
|||
|
|
if (item.RetVal == workerResponse)
|
|||
|
|
{
|
|||
|
|
if (item.NewState != IdcState.Unchanged) idcState = item.NewState;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return workerResponse;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Shut down Idc100 operation, stop the worker thread.
|
|||
|
|
/// </summary>
|
|||
|
|
public void ShutDown()
|
|||
|
|
{
|
|||
|
|
if (workerThread != null) workerThread.Join();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Worker()
|
|||
|
|
{
|
|||
|
|
//-------------------------------------------------------------------
|
|||
|
|
// Introductory part: 'Connect' operation waits until it is completed
|
|||
|
|
//-------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/// Open the COM-port and set communication parameters
|
|||
|
|
workerResponse = serial.OpenPort();
|
|||
|
|
|
|||
|
|
/// Verify connection and get version
|
|||
|
|
if (RetVal.OK == workerResponse && RetVal.OK != serial.GetVer(out cameraVersionStr))
|
|||
|
|
{
|
|||
|
|
serial.ClosePort();
|
|||
|
|
workerResponse = RetVal.CannotCommWithCamera;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Signal intro is finished, return on error
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
if (workerResponse != RetVal.OK) return; /// Thread halted on error
|
|||
|
|
|
|||
|
|
//--------------------------------------------------
|
|||
|
|
// Worker thread loop
|
|||
|
|
//--------------------------------------------------
|
|||
|
|
string cmd;
|
|||
|
|
RetVal retv;
|
|||
|
|
int iretv;
|
|||
|
|
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
workerCommandEvent.WaitOne();
|
|||
|
|
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
if (workerCmd is Command.Disconnect)
|
|||
|
|
{
|
|||
|
|
// Disconnect camera: close the com-port and exit worker thread
|
|||
|
|
serial.ClosePort();
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.StopOp)
|
|||
|
|
{
|
|||
|
|
// StopOp() when camera is idle -> do nothing
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.StartNew)
|
|||
|
|
{
|
|||
|
|
// Format:
|
|||
|
|
// startnew
|
|||
|
|
// Issues command(s):
|
|||
|
|
// startnew
|
|||
|
|
// settime <year> <month> <date> <hour> <min> <sec>
|
|||
|
|
byte znak;
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
serial.WriteString("startnew\r\n");
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
// Returns:
|
|||
|
|
// WAIT_OBJECT_0 ... WorkerCommand.STOP_OP received
|
|||
|
|
// WAIT_TIMEOUT .... time expired, no WorkerCommand.STOP_OP received
|
|||
|
|
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
if (workerCommandEvent.WaitOne(6000))
|
|||
|
|
{
|
|||
|
|
/// Signal received
|
|||
|
|
if (workerCmd is Command.StopOp)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpInterrupted;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/// Timeout
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (workerResponse == RetVal.OK)
|
|||
|
|
{
|
|||
|
|
do {
|
|||
|
|
retv = serial.ReadByte(out znak);
|
|||
|
|
}
|
|||
|
|
while (znak != '$'); // read all characters in the buffer
|
|||
|
|
|
|||
|
|
serial.WriteString("connect\r\n");
|
|||
|
|
|
|||
|
|
if (RetVal.OK != serial.ReadByte(out znak) || znak != 'V') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\r') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\n') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '$') workerResponse = RetVal.OpFailed;
|
|||
|
|
else workerResponse = RetVal.OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (workerResponse == RetVal.OK)
|
|||
|
|
{
|
|||
|
|
/// settime
|
|||
|
|
DateTime now = DateTime.Now;
|
|||
|
|
string settimeStr = String.Format("settime {0} {1} {2} {3} {4} {5} {6}\r\n",
|
|||
|
|
now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
|
|||
|
|
serial.WriteString(settimeStr);
|
|||
|
|
|
|||
|
|
if (RetVal.OK != serial.ReadByte(out znak) || znak != '>') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != ' ') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '0') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != ' ') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != 'O') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != 'K') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\r') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '\n') workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (RetVal.OK != serial.ReadByte(out znak) || znak != '$') workerResponse = RetVal.OpFailed;
|
|||
|
|
else workerResponse = RetVal.OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Verify connection and get version
|
|||
|
|
if (RetVal.OK == workerResponse && RetVal.OK != serial.GetVer(out cameraVersionStr))
|
|||
|
|
{
|
|||
|
|
serial.ClosePort();
|
|||
|
|
workerResponse = RetVal.CannotCommWithCamera;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
WT_SSOp_Complete(workerResponse);
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.SetBrightness)
|
|||
|
|
{
|
|||
|
|
Command.SetBrightness args = workerCmd as Command.SetBrightness;
|
|||
|
|
|
|||
|
|
/// Set image brightness
|
|||
|
|
/// Format: setbright 0..100
|
|||
|
|
/// Example: setbright 50
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
|
|||
|
|
workerResponse = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Grab)
|
|||
|
|
{
|
|||
|
|
Command.Grab args = workerCmd as Command.Grab;
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(String.Format("new matbyte snap({0},{1}) vecint iroi(5)\r\n", args.W, args.H),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(String.Format("set iroi {0} {1} {2} {3} {4}\r\n",
|
|||
|
|
args.X, args.Y, args.W, args.H, args.Scale),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// grab
|
|||
|
|
iretv = serial.CommandInt(String.Format("grab snap iroi\r\n"),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// save
|
|||
|
|
string fmtStr = (args.Format == FileFormat.Bmp) ? "bmp" : ( (args.Format == FileFormat.Jpeg) ? "jpg" : "idc");
|
|||
|
|
cmd = string.Format("save {0} snap {1}\r\n", fmtStr, args.FileName);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
workerResponse = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Save)
|
|||
|
|
{
|
|||
|
|
Command.Save args = workerCmd as Command.Save;
|
|||
|
|
|
|||
|
|
string fmtStr = (args.Format == FileFormat.Bmp) ? "bmp" : ( (args.Format == FileFormat.Jpeg) ? "jpg" : "idc");
|
|||
|
|
cmd = string.Format("save {0} {1} {2}\r\n", fmtStr, args.VariableName, args.FileName);
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
// NOK
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
else if (!args.WaitCompleted)
|
|||
|
|
{
|
|||
|
|
// OK and does not wait for completition
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// OK, but waits for completition
|
|||
|
|
workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(200);
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt("fiostate\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] <= 0)
|
|||
|
|
{
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_OP_COMPLETED+m_cameraNr, 0); <------- TODO
|
|||
|
|
idcState = IdcState.OpCompleted;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
|
|||
|
|
// OK & completed
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
/*
|
|||
|
|
///---------------------------------------
|
|||
|
|
/// Releases IDC100 memory allocated by created images and variables
|
|||
|
|
/// and deletes oroi1 ... oroi9 (complete detection result)
|
|||
|
|
/// Format: clear
|
|||
|
|
///---------------------------------------
|
|||
|
|
case WorkerCommand.NEW_WM:
|
|||
|
|
{
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt("delete -all\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt("new int nrarrows\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(String.Format("set nrarrows {0}\r\n", arrows.GetLength(0) - 1), out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.OK; /// Eventually overwritten in the for loop
|
|||
|
|
//------
|
|||
|
|
for (int arwIx = 1; arwIx <= arrows.GetLength(0) - 1; arwIx++)
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("new vecfloat params{0}({1}) vecint oroi{0}(5) matshort bkgnd{0}({2},{3}) matbyte detected{0}({4},{5})\r\n",
|
|||
|
|
arwIx, ParamsSize, (int)(Math.Round(arrows[arwIx].oroi_w)), (int)(Math.Round(arrows[arwIx].oroi_h)),
|
|||
|
|
arrows[arwIx].iroi_w, arrows[arwIx].iroi_h);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cmd = String.Format("set params{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14}\r\n",
|
|||
|
|
arwIx, ParamsSize,
|
|||
|
|
arrows[arwIx].wmType,
|
|||
|
|
arrows[arwIx].cx.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].cy.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].oroi_w.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].oroi_h.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].r1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].r2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].r3.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].a1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].a2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].step_a.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].nom_speed.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
arrows[arwIx].background_corr);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cmd = String.Format("set oroi{0} 0 0 {1} {2} 1\r\n",
|
|||
|
|
arwIx, (int)(Math.Round(arrows[arwIx].oroi_w)), (int)(Math.Round(arrows[arwIx].oroi_h)));
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv==0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
} //for
|
|||
|
|
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Detect)
|
|||
|
|
{
|
|||
|
|
Command.Detect args = workerCmd as Command.Detect;
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
/// Common commands:
|
|||
|
|
cmd = "delete -ex oroi1 oroi2 bkgnd1 bkgnd2 detected1 detected2\r\n";
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd("loadflash\r\n")))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("new vecfloat params{0}({1}) vecint oroi{0}(5) matshort bkgnd{0}({2},{3}) matbyte detected{0}({4},{5})\r\n",
|
|||
|
|
args.RoiNr,
|
|||
|
|
ParamsSize,
|
|||
|
|
(int)Math.Round(args.ORoiW),
|
|||
|
|
(int)Math.Round(args.ORoiH),
|
|||
|
|
args.IRoiW,
|
|||
|
|
args.IRoiH);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("set params{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14}\r\n",
|
|||
|
|
args.RoiNr,
|
|||
|
|
ParamsSize,
|
|||
|
|
args.WMeterType,
|
|||
|
|
args.CX.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.CY.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.ORoiW.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.ORoiH.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.R1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.R2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.R3.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.Ang1.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.Ang2.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.AngStep.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.NomSpeed.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
args.BackgroundCorr);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("set oroi{0} 0 0 {1} {2} 1\r\n",
|
|||
|
|
args.RoiNr, (int)Math.Round(args.ORoiW), (int)Math.Round(args.ORoiH));
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
if (args.WMeterType == 0)
|
|||
|
|
{
|
|||
|
|
///
|
|||
|
|
/// wmType==0 commands:
|
|||
|
|
///
|
|||
|
|
cmd = String.Format("new vecint iroi{0}(5) periods timestamps cubbyte seq\r\n", args.RoiNr);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n",
|
|||
|
|
args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
StringBuilder sb = new StringBuilder(40);
|
|||
|
|
for (int i = 0; i < args.SequenceLen; i++)
|
|||
|
|
{
|
|||
|
|
sb.Append(" ");
|
|||
|
|
sb.Append((i % 2 == 0) ? "1" : args.SequenceTiming.ToString());
|
|||
|
|
}
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(String.Format("set periods{0}\r\n", sb.ToString()))))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("grab seq iroi{0} {1} periods timestamps\r\n",
|
|||
|
|
args.RoiNr, args.SequenceLen);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_LongCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
switch (args.RoiNr)
|
|||
|
|
{
|
|||
|
|
default: retv = 0; break;
|
|||
|
|
case 2: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi2 oroi1\r\n"); break;
|
|||
|
|
case 3: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi3 oroi1 oroi2\r\n"); break;
|
|||
|
|
case 4: retv = WT_SSOp_LongCmd_NoTmOut("mask seq iroi4 oroi1 oroi2 oroi3\r\n"); break;
|
|||
|
|
}
|
|||
|
|
if (RetVal.OK == retv)
|
|||
|
|
{
|
|||
|
|
retv = WT_SSOp_LongCmd(String.Format("detect {0} seq periods detected{0}\r\n",
|
|||
|
|
args.RoiNr));
|
|||
|
|
|
|||
|
|
if (retv == RetVal.OK)
|
|||
|
|
{
|
|||
|
|
// save
|
|||
|
|
cmd = string.Format("save jpg detected{0} detected{0}\r\n", args.RoiNr);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
|
|||
|
|
RetVal retv2 = (iretv <= 0 || received[0] < 0) ? RetVal.OpFailed : RetVal.OK;
|
|||
|
|
if (retv2 == RetVal.OpInterrupted) retv = RetVal.OpInterrupted;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (args.WMeterType >= 1)
|
|||
|
|
{ //
|
|||
|
|
// wmType==1,2 commands:
|
|||
|
|
//
|
|||
|
|
cmd = String.Format("new matfloat homo vecint iroi{0}(5) cubbyte seq cubshort c1 matshort strip lsdbkg digits0\r\n", args.RoiNr);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n", args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH);
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_FastCmd(cmd)))
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("grab seq iroi{0} 20 11\r\n", args.RoiNr))))
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("detect {0} seq 1 detected{0} homo\r\n", args.RoiNr))))
|
|||
|
|
{
|
|||
|
|
// time 95s +/- 1.5 turns
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_LongCmd(String.Format("grab c1 oroi{0} 300 7\r\n", args.RoiNr))))
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK == (retv = WT_SSOp_LongCmd_NoTmOut(String.Format("mount c1 oroi{0} homo strip lsdbkg 0\r\n", args.RoiNr))))
|
|||
|
|
{
|
|||
|
|
retv = WT_SSOp_LongCmd("getdigits strip digits0\r\n");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
WT_SSOp_Complete(retv);
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
/*
|
|||
|
|
case WorkerCommand.VERIFY:
|
|||
|
|
{
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt("verify\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OP_FAILED;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.BUSY; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Measure)
|
|||
|
|
{
|
|||
|
|
Command.Measure args = workerCmd as Command.Measure;
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int logLen = 400000 / (int)Math.Round(args.ORoiW) / (int)Math.Round(args.ORoiH);
|
|||
|
|
if (logLen < 2) logLen = 2;
|
|||
|
|
|
|||
|
|
if (args.WMeterType == 0)
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("new vecint iroi{0}(5) snaptimes(10) cubshort snaps({1},{2},10) log({1},{2},{3}) int shift\r\n",
|
|||
|
|
args.RoiNr, (int)Math.Round(args.ORoiW), (int)Math.Round(args.ORoiH), logLen);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
cmd = String.Format("new vecint iroi{0}(5) snaptimes(10) cubshort snaps({1},{2},10) lsdlog int shift\r\n",
|
|||
|
|
args.RoiNr, (int)Math.Round(args.CX), (int)Math.Round(args.CY)); // snaps(cx,cy,10) ... dimensions
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv<=0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cmd = String.Format("set iroi{0} {1} {2} {3} {4} 1\r\n",
|
|||
|
|
args.RoiNr, args.IRoiX, args.IRoiY, args.IRoiW, args.IRoiH);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
cmd = String.Format("getshift seq iroi{0} shift {1}\r\n", args.RoiNr, 30);
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if (args.WMeterType == 0 && args.MaxMvmt == 0 && args.MinMvmt == 0)
|
|||
|
|
{
|
|||
|
|
///
|
|||
|
|
/// Std: Uses 'initSpeed'
|
|||
|
|
///
|
|||
|
|
cmd = String.Format("task 1 oroi{0} 1 {1} {2} shift snaps snaptimes log {3} params{0} bkgnd{0}\r\n",
|
|||
|
|
args.RoiNr,
|
|||
|
|
MesurementPeriod_Frames,
|
|||
|
|
(args.Triggered ? "1" : "0"),
|
|||
|
|
logLen);
|
|||
|
|
serial.FifoFlush();
|
|||
|
|
serial.WriteString(cmd); // send command
|
|||
|
|
}
|
|||
|
|
else if (args.WMeterType == 0)
|
|||
|
|
{
|
|||
|
|
//
|
|||
|
|
// Introduced in ver.7.6.7:
|
|||
|
|
// Uses 'maxMvmt' and 'minMvmt', allows faster movement measurement
|
|||
|
|
//
|
|||
|
|
cmd = String.Format("task 1 oroi{0} 1 {1} {2} shift snaps snaptimes log {3} params{0} bkgnd{0} {4} {5}\r\n",
|
|||
|
|
args.RoiNr,
|
|||
|
|
MesurementPeriod_Frames,
|
|||
|
|
(args.Triggered ? "1" : "0"),
|
|||
|
|
logLen,
|
|||
|
|
args.MaxMvmt,
|
|||
|
|
args.MinMvmt);
|
|||
|
|
serial.FifoFlush();
|
|||
|
|
serial.WriteString(cmd); // send command
|
|||
|
|
}
|
|||
|
|
else if (args.WMeterType >= 1)
|
|||
|
|
{
|
|||
|
|
//
|
|||
|
|
// Digital counters (Dubai)
|
|||
|
|
//
|
|||
|
|
cmd = String.Format("task {0} oroi{1} 1 {2} {3} shift snaps snaptimes 0 0 homo digits0 params{1} lsdbkg 36 lsdlog\r\n",
|
|||
|
|
args.WMeterType + 1,
|
|||
|
|
args.RoiNr,
|
|||
|
|
MesurementPeriod_Frames,
|
|||
|
|
(args.Triggered ? "1" : "0"));
|
|||
|
|
serial.FifoFlush();
|
|||
|
|
serial.WriteString(cmd); // send command
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// clear measurement data
|
|||
|
|
measurements.Clear();
|
|||
|
|
wm_nrBegin = 0;
|
|||
|
|
wm_nrEnd = 0;
|
|||
|
|
wm_timestampBegin = 0;
|
|||
|
|
wm_timestampEnd = 0;
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
// start reading data
|
|||
|
|
byte znak;
|
|||
|
|
bool stopOpReceived = false;
|
|||
|
|
int angle;
|
|||
|
|
uint time;
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
// wait for '>' character, check for WorkerCommand.STOP_OP
|
|||
|
|
do {
|
|||
|
|
if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5))
|
|||
|
|
{
|
|||
|
|
stopOpReceived = true;
|
|||
|
|
serial.WriteByte((byte)'Q');
|
|||
|
|
}
|
|||
|
|
if (RetVal.OK != (retv = serial.ReadByte(out znak))) /// if ReadByte_C fails => quit the loop ...
|
|||
|
|
{ /// ... and return negative error code
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
while (znak != '>');
|
|||
|
|
|
|||
|
|
if (retv != RetVal.OK) break; /// communication failed
|
|||
|
|
|
|||
|
|
/// Read the rest of line
|
|||
|
|
StringBuilder restOfLine = new StringBuilder();
|
|||
|
|
while (RetVal.OK == (retv = serial.ReadByte(out znak)) &&
|
|||
|
|
(znak != (byte)'\r') && (znak != (byte)'\n'))
|
|||
|
|
{
|
|||
|
|
restOfLine.Append((char)znak);
|
|||
|
|
}
|
|||
|
|
if (retv != RetVal.OK) break;
|
|||
|
|
|
|||
|
|
log.InfoFormat("Received: >{0}", restOfLine);
|
|||
|
|
|
|||
|
|
/// Parse the line, save and send the result
|
|||
|
|
string[] results = restOfLine.ToString().Split(new char[] { ' ' });
|
|||
|
|
if ((results.Length >= 3) && results[1].Equals("0") && results[2].Equals("OK"))
|
|||
|
|
{
|
|||
|
|
retv = RetVal.OK; /// Op. successfully completed
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
else if (results.Length < 3 || !UInt32.TryParse(results[1], out time) || !Int32.TryParse(results[2], out angle))
|
|||
|
|
{
|
|||
|
|
retv = RetVal.OpFailed; /// Op. failed
|
|||
|
|
log.ErrorFormat("RetVal.OpFailed", restOfLine);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!stopOpReceived)
|
|||
|
|
{
|
|||
|
|
if ((time > 0) && (measurements.Count < MaxMeasurementsCount))
|
|||
|
|
{
|
|||
|
|
if (angle == (int)MARK.DUMMY)
|
|||
|
|
{
|
|||
|
|
// do nothing
|
|||
|
|
}
|
|||
|
|
else if (angle == (int)MARK.FALLING)
|
|||
|
|
{
|
|||
|
|
wm_nrBegin = measurements.Count;
|
|||
|
|
wm_timestampBegin = time;
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, ID_BEGIN); <------- TODO
|
|||
|
|
}
|
|||
|
|
else if (angle == (int)MARK.RISING)
|
|||
|
|
{
|
|||
|
|
wm_nrEnd = measurements.Count;
|
|||
|
|
wm_timestampEnd = time;
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, ID_END); <------- TODO
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
measurements.Add(new Measurement(time, angle));
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_DATA_READY+m_cameraNr, wm_nrmeasurements); <------- TODO
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (retv == RetVal.OK && time == 0)
|
|||
|
|
{
|
|||
|
|
/// Wait until '$'
|
|||
|
|
do {
|
|||
|
|
if (RetVal.OK != (retv = serial.ReadByte(out znak))) /// if ReadByte_C fails => quit ...
|
|||
|
|
break; //return -retv; /// ... the loop and return negative ...
|
|||
|
|
} /// ... error code
|
|||
|
|
while (znak != '$');
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (retv != RetVal.OK && !stopOpReceived)
|
|||
|
|
{
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_OP_FAILED+m_cameraNr, 0); <------- TODO
|
|||
|
|
idcState = IdcState.OpFailed;
|
|||
|
|
WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Other)
|
|||
|
|
{
|
|||
|
|
Command.Other args = workerCmd as Command.Other;
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(args.Command + "\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv < 0) workerResponse = (RetVal)(-iretv);
|
|||
|
|
else if (iretv==0) workerResponse = RetVal.OpFailed;
|
|||
|
|
else if (received[0] < 0) workerResponse = (RetVal)(-received[0]);
|
|||
|
|
else workerResponse = RetVal.OK;
|
|||
|
|
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.Stream)
|
|||
|
|
{
|
|||
|
|
Command.Stream args = workerCmd as Command.Stream;
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
/// Check the camera file I/O state
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
iretv = serial.CommandInt("fiostate\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
else if (received[0] == 0)
|
|||
|
|
{
|
|||
|
|
break; /// Continue - start a stream operation
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
iretv = serial.CommandInt(string.Format("setbright {0}\r\n", Math.Max(0, Math.Min((int)(100.0f * args.Brightness), 100))),
|
|||
|
|
out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Grab one image
|
|||
|
|
if (args.Type != StreamType.Full)
|
|||
|
|
{
|
|||
|
|
iretv = serial.CommandInt("acqimage\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv <= 0 || received[0] < 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OpFailed;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Prepare the camera command string
|
|||
|
|
if (args.Format == FileFormat.Bmp)
|
|||
|
|
{
|
|||
|
|
if (args.Type == StreamType.SubSampled) cmd = "streamssdbmp\r\n";
|
|||
|
|
else if (args.Type == StreamType.Focus) cmd = "streamroibmp\r\n";
|
|||
|
|
else cmd = "streambmp\r\n";
|
|||
|
|
}
|
|||
|
|
else if (args.Format == FileFormat.Jpeg)
|
|||
|
|
{
|
|||
|
|
if (args.Type == StreamType.SubSampled) cmd = "streamssdjpg\r\n";
|
|||
|
|
else if (args.Type == StreamType.Focus) cmd = "streamroijpg\r\n";
|
|||
|
|
else cmd = "streamjpg\r\n";
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OK;
|
|||
|
|
workerEvent.Set();
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Start streaming
|
|||
|
|
iretv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
|
|||
|
|
if (iretv >= 1 && received[0] == 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.Busy; // state -> State.CAMERA_BUSY
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
WorkerCommand wrkCmd = WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
|
|||
|
|
/// Stop streaming
|
|||
|
|
iretv = serial.CommandInt("stopstream\r\n", out received, 1, out m_errorStr);
|
|||
|
|
if (iretv >= 1 && received[0] == 0)
|
|||
|
|
{
|
|||
|
|
workerResponse = RetVal.OK; // state -> State.CAMERA_IDLE
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
if (wrkCmd != WorkerCommand.StopOp)
|
|||
|
|
{
|
|||
|
|
WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
workerResponse = RetVal.OK; // state: State.CAMERA_OP_COMPLETED -> State.CAMERA_IDLE or
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/// Streaming was not started, return error and wait for StopOp
|
|||
|
|
workerResponse = RetVal.OpFailed; // state -> State.CAMERA_OP_FAILED
|
|||
|
|
workerEvent.Set();
|
|||
|
|
|
|||
|
|
WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
|
|||
|
|
workerResponse = RetVal.OK; // state -> State.CAMERA_IDLE
|
|||
|
|
workerEvent.Set();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//-------------------------------------------------------------------------------------------
|
|||
|
|
else if (workerCmd is Command.StopStream)
|
|||
|
|
{
|
|||
|
|
Command.StopStream args = workerCmd as Command.StopStream;
|
|||
|
|
}
|
|||
|
|
} // end while (true)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
// Sends command and waits for a response.
|
|||
|
|
//
|
|||
|
|
// Arguments:
|
|||
|
|
// cmd ........ command
|
|||
|
|
// Returns:
|
|||
|
|
// long ... 0 = command completed OK, error code=0
|
|||
|
|
// 1...999 = command completed with an error code
|
|||
|
|
// RetVal.OP_INTERRUPTED = StopOp was received by the OCX component
|
|||
|
|
// 1000... = camera error (communication timeout ?)
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
RetVal WT_SSOp_FastCmd(string cmd)
|
|||
|
|
{
|
|||
|
|
if (WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(1))
|
|||
|
|
{
|
|||
|
|
return RetVal.OpInterrupted; /// This error code has the priority to avoid deadlocks
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int[] received = new int[1];
|
|||
|
|
received[0] = 0; /// OK in debug mode
|
|||
|
|
|
|||
|
|
/// Send a command that cannot be interrupted via 'Q'
|
|||
|
|
int readByteRetv = serial.CommandInt(cmd, out received, 1, out m_errorStr);
|
|||
|
|
|
|||
|
|
if (readByteRetv<0) return (RetVal)(-readByteRetv); /// possibly a camera timeout
|
|||
|
|
|
|||
|
|
return (RetVal)(-received[0]); /// <--- normal return from the operation
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
// Sends command and waits for "> 'received' 'string'" or sends 'Q'
|
|||
|
|
// after CMD_STOP_OP. Then waits for a prompt '$'.
|
|||
|
|
// Waits until '>' is received.
|
|||
|
|
//
|
|||
|
|
// Arguments:
|
|||
|
|
// cmd ........ command
|
|||
|
|
// Returns:
|
|||
|
|
// long ... 0 = command completed OK, error code=0
|
|||
|
|
// 1...999 = command completed with an error code
|
|||
|
|
// RetVal.OP_INTERRUPTED = StopOp was received by the OCX component
|
|||
|
|
// 1000... = camera error (communication timeout ?)
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
RetVal WT_SSOp_LongCmd(string cmd)
|
|||
|
|
{
|
|||
|
|
/// Send the command
|
|||
|
|
serial.FifoFlush();
|
|||
|
|
serial.WriteString(cmd);
|
|||
|
|
|
|||
|
|
RetVal readByteRetv;
|
|||
|
|
byte znak;
|
|||
|
|
|
|||
|
|
/// When WorkerCommand.STOP_OP arrives, 'Q' character is sent to abort the operation.
|
|||
|
|
/// Then the loop still waits until '>' is received.
|
|||
|
|
bool stopOpReceived = false;
|
|||
|
|
do {
|
|||
|
|
if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5))
|
|||
|
|
{
|
|||
|
|
/// send 'Q' if CMD_STOP_OP worker thread command is received
|
|||
|
|
stopOpReceived = true;
|
|||
|
|
serial.WriteByte((byte)'Q');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break;
|
|||
|
|
/// if ReadByte_C fails quit the loop and return negative error code
|
|||
|
|
}
|
|||
|
|
while (znak != (byte)'>');
|
|||
|
|
|
|||
|
|
if (stopOpReceived) return RetVal.OpInterrupted; /// StopOp: This error code has the priority to avoid deadlocks
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout
|
|||
|
|
|
|||
|
|
/// Read a line of text from IDC terminated by '\r' (and '\n')
|
|||
|
|
StringBuilder tmp = new StringBuilder();
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break;
|
|||
|
|
if (znak == (byte)'\r') break;
|
|||
|
|
tmp.Append((char)znak);
|
|||
|
|
}
|
|||
|
|
while (true);
|
|||
|
|
|
|||
|
|
log.InfoFormat("{0}: Received: >{1}", cameraNr, tmp);
|
|||
|
|
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Return on error
|
|||
|
|
|
|||
|
|
/// Parse the line after '>'.
|
|||
|
|
/// Read two fields: Return code and the rest of the line.
|
|||
|
|
const int maxArrayLen = 3;
|
|||
|
|
string[] strArray = tmp.ToString().Split(new char[] {' '}, maxArrayLen);
|
|||
|
|
///
|
|||
|
|
if (strArray.Length < 3) return RetVal.CommError; /// Unexpected format, there should be at least 2 strings
|
|||
|
|
///
|
|||
|
|
int negativeIdcReturnCode;
|
|||
|
|
if (!Int32.TryParse(strArray[1], out negativeIdcReturnCode))
|
|||
|
|
{
|
|||
|
|
return RetVal.CommError;
|
|||
|
|
}
|
|||
|
|
else if (negativeIdcReturnCode < 0)
|
|||
|
|
{
|
|||
|
|
m_errorStr = strArray[2];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Read characters until '$' received
|
|||
|
|
do {
|
|||
|
|
if (0 != (readByteRetv = serial.ReadByte(out znak))) break;
|
|||
|
|
}
|
|||
|
|
while (znak != '$');
|
|||
|
|
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout
|
|||
|
|
|
|||
|
|
return (RetVal)(-negativeIdcReturnCode); /// Normal return from the operation
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//----------------------------------------------------------------------------
|
|||
|
|
// Sends command and waits for "> 'received' 'string'" or sends 'Q'
|
|||
|
|
// after CMD_STOP_OP. Then waits for a prompt '$'.
|
|||
|
|
//
|
|||
|
|
// Arguments:
|
|||
|
|
// cmd ........ command
|
|||
|
|
// Returns:
|
|||
|
|
// long ... 0 = command completed OK, error code=0
|
|||
|
|
// 1...999 = command completed with an error code
|
|||
|
|
// RetVal.OP_INTERRUPTED = StopOp was received by the OCX component
|
|||
|
|
// 1000... = camera error (communication timeout ?)
|
|||
|
|
//----------------------------------------------------------------------------
|
|||
|
|
RetVal WT_SSOp_LongCmd_NoTmOut(string cmd)
|
|||
|
|
{
|
|||
|
|
/// Send the command
|
|||
|
|
serial.FifoFlush();
|
|||
|
|
serial.WriteString(cmd);
|
|||
|
|
|
|||
|
|
RetVal readByteRetv;
|
|||
|
|
byte znak;
|
|||
|
|
|
|||
|
|
/// When WorkerCommand.STOP_OP arrives, 'Q' character is sent to abort the operation.
|
|||
|
|
/// Then the loop still waits until '>' is received.
|
|||
|
|
bool stopOpReceived = false;
|
|||
|
|
do {
|
|||
|
|
if (!stopOpReceived && WorkerCommand.StopOp == WT_SSOp_Wait4StopOp(5))
|
|||
|
|
{
|
|||
|
|
// send 'Q' if CMD_STOP_OP worker thread command is received
|
|||
|
|
stopOpReceived = true;
|
|||
|
|
serial.WriteByte((byte)'Q');
|
|||
|
|
}
|
|||
|
|
readByteRetv = serial.ReadByte(out znak); /// Do not quit the loop on timeout (???)
|
|||
|
|
}
|
|||
|
|
while (znak != '>');
|
|||
|
|
|
|||
|
|
if (stopOpReceived) return RetVal.OpInterrupted; /// StopOp: This error code has the priority to avoid deadlocks
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout
|
|||
|
|
|
|||
|
|
/// Read a line of text from IDC terminated by '\r' (and '\n')
|
|||
|
|
StringBuilder tmp = new StringBuilder();
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (RetVal.OK != (readByteRetv = serial.ReadByte(out znak))) break;
|
|||
|
|
if (znak == (byte)'\r') break;
|
|||
|
|
tmp.Append((char)znak);
|
|||
|
|
}
|
|||
|
|
while (true);
|
|||
|
|
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Return on error
|
|||
|
|
|
|||
|
|
/// Parse the line after '>'.
|
|||
|
|
/// Read two fields: Return code and the rest of the line.
|
|||
|
|
const int maxArrayLen = 2;
|
|||
|
|
string[] strArray = tmp.ToString().Split(new char[] { ' ' }, maxArrayLen);
|
|||
|
|
///
|
|||
|
|
if (strArray.Length < 2) return RetVal.OpFailed; /// Unexpected format, there should be at least 2 strings
|
|||
|
|
///
|
|||
|
|
int negativeIdcReturnCode;
|
|||
|
|
Int32.TryParse(strArray[0], out negativeIdcReturnCode);
|
|||
|
|
if (negativeIdcReturnCode < 0) m_errorStr = strArray[1];
|
|||
|
|
|
|||
|
|
/// Read characters until '$' received
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (0 != (readByteRetv = serial.ReadByte(out znak))) break;
|
|||
|
|
}
|
|||
|
|
while (znak != '$');
|
|||
|
|
|
|||
|
|
if (readByteRetv != RetVal.OK) return readByteRetv; /// Possibly a camera communication timeout
|
|||
|
|
|
|||
|
|
return (RetVal)(-negativeIdcReturnCode); /// Normal return from the operation
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
// Sends OP_COPMPETED / OP_FAILED message and waits for StopOp.
|
|||
|
|
//
|
|||
|
|
// Arguments:
|
|||
|
|
// errorCode ... RetVal.OP_INTERRUPTED, !!!do not issue any message anymore
|
|||
|
|
// < 1000 command line response (number after >), or
|
|||
|
|
// >=1000 error code (camera timeout, etc.)
|
|||
|
|
// Returns:
|
|||
|
|
// long ........ 0 = OK ... 'received' is valid
|
|||
|
|
// RetVal.COMM_TIEMOUT
|
|||
|
|
//---------------------------------------------------------------------
|
|||
|
|
void WT_SSOp_Complete(RetVal errorCode)
|
|||
|
|
{
|
|||
|
|
if (errorCode == RetVal.OpInterrupted) return;
|
|||
|
|
|
|||
|
|
// Send an appropriate message to the control
|
|||
|
|
if (errorCode == RetVal.OK)
|
|||
|
|
{
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_OP_COMPLETED+m_cameraNr, 0); <------- TODO
|
|||
|
|
idcState = IdcState.OpCompleted;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//m_pWnd->PostMessage(WM_USER, EVENT_OP_FAILED+m_cameraNr, -errorCode); <------- TODO
|
|||
|
|
idcState = IdcState.OpFailed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Wait for StopOp
|
|||
|
|
WT_SSOp_Wait4StopOp(Timeout.Infinite);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** ------------------------------------------------------------------------------
|
|||
|
|
* Waits for CMD_STOP_OP command. Other commands are ignoerd.
|
|||
|
|
*
|
|||
|
|
* Arguments:
|
|||
|
|
* ms .............. timeout in ms or INFINITE (default)
|
|||
|
|
* Returns:
|
|||
|
|
* WorkerCommand.STOP_OP ... STOP_OP received
|
|||
|
|
* WorkerCommand.Timeout ... time expired, no STOP_OP received
|
|||
|
|
* ------------------------------------------------------------------------------- */
|
|||
|
|
WorkerCommand WT_SSOp_Wait4StopOp(int timeoutMs)
|
|||
|
|
{
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
if (workerCommandEvent.WaitOne(timeoutMs))
|
|||
|
|
{
|
|||
|
|
if (workerCmd is Command.StopOp) return WorkerCommand.StopOp;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return WorkerCommand.Timeout;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|