325 lines
8.4 KiB
C++
325 lines
8.4 KiB
C++
#ifndef SHIMLCCONTROLLER_H
|
|
#define SHIMLCCONTROLLER_H
|
|
#include <QtCore/QObject>
|
|
#include <QtNetwork>
|
|
#include <QDebug>
|
|
#include <QtLogging>
|
|
#include <QtEndian>
|
|
#include <QTextCodec>
|
|
#include <QObject>
|
|
#include <QList>
|
|
#include <tuple>
|
|
#include <cmath>
|
|
#include <QAbstractSocket>
|
|
#include <QMessageBox>
|
|
#include <QtEndian>
|
|
|
|
#define INBOUND(val, upper, lower) val >= lower && val <= upper
|
|
|
|
struct ShimLCCmdStackResult
|
|
{
|
|
ShimLCCmdStackResult(uint32_t id, QByteArray data)
|
|
: id(id), data(data) {}
|
|
uint32_t id;
|
|
QByteArray data;
|
|
};
|
|
|
|
enum ParserMode
|
|
{
|
|
ParseQuery, ParseCbmir, ParseCbmiw
|
|
};
|
|
|
|
// ---
|
|
|
|
class ShimTCPController : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
int irPendingSize = -1;
|
|
void cbmquery(QString message);
|
|
void cbmir(quint8 filehandle, QByteArray* irDataRet = nullptr);
|
|
void cbmiw(quint8 filehandle, QByteArray* irDataToSend = nullptr);
|
|
explicit ShimTCPController(QObject *parent = 0);
|
|
~ShimTCPController();
|
|
|
|
private slots:
|
|
bool writeData(QByteArray *data);
|
|
void readData();
|
|
void displayError(QAbstractSocket::SocketError socketError);
|
|
|
|
void parseCbmquery(QByteArray data);
|
|
void parseCbmIr();
|
|
void parseCbmIw();
|
|
|
|
void dataAvailableErrorNoF(QByteArray data);
|
|
void emitConnectionStateChanged();
|
|
|
|
public slots:
|
|
void connectToHost(QString host, int port);
|
|
|
|
signals:
|
|
void irDone();
|
|
void dataAvailable(QByteArray data);
|
|
void connectionStateChanged(QAbstractSocket::SocketState state);
|
|
|
|
private:
|
|
QString TAG = "ShimTCPController";
|
|
QTcpSocket *socket;
|
|
QByteArray next_pkg{};
|
|
int irFileHandle = -1;
|
|
QByteArray* irData = nullptr;
|
|
QByteArray* pendingData = nullptr;
|
|
ParserMode mode = ParseQuery;
|
|
};
|
|
|
|
// ---
|
|
|
|
class ShimLCCommandStack : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
void exitedIr();
|
|
void newResult(QByteArray data);
|
|
|
|
signals:
|
|
void dataAvailable(uint32_t id);
|
|
void connectionStateChanged(QAbstractSocket::SocketState state);
|
|
|
|
public:
|
|
explicit ShimLCCommandStack(QObject *parent = 0);
|
|
~ShimLCCommandStack();
|
|
uint32_t setVal(QString cmd, QByteArray *dest);
|
|
uint32_t getSetVal(QString cmd, QByteArray *dest);
|
|
uint32_t getActVal(QString cmd, QByteArray *dest);
|
|
uint32_t readFile(QString filename, QByteArray *dest, uint size);
|
|
uint32_t writeFile(QString filename, QByteArray *data);
|
|
void reconnect(QSettings *settings);
|
|
|
|
private:
|
|
|
|
QString TAG = "ShimLCCommandStack";
|
|
using Connection = std::tuple<QObject*, const char*>;
|
|
struct ShimLCCmd
|
|
{
|
|
ShimLCCmd(uint32_t id, char opcode, QString cmd, QByteArray* dest, uint32_t iSize)
|
|
: id(id), opcode(opcode), cmd(cmd), dest(dest), iSize(iSize) {}
|
|
uint32_t id;
|
|
char opcode;
|
|
QString cmd;
|
|
QByteArray* dest;
|
|
uint32_t iSize; // Only needed for I commands
|
|
};
|
|
ShimTCPController connection{};
|
|
QVector<ShimLCCmd> stackIn{};
|
|
uint32_t id = 0;
|
|
uint32_t busy_id = 0;
|
|
|
|
void next();
|
|
uint32_t addCmd(char opcode, QString cmd, QByteArray* dest, uint iSize = 0);
|
|
|
|
QObject* parent;
|
|
};
|
|
|
|
// ---
|
|
|
|
struct LCPort
|
|
{
|
|
LCPort(uint8_t port, uint8_t id, QString name, QString version, QString serial)
|
|
: port(port), id(id), name(name), version(version), serial(serial) {}
|
|
uint8_t port;
|
|
uint8_t id;
|
|
QString name;
|
|
QString version;
|
|
QString serial;
|
|
};
|
|
|
|
/* Param [Unit] | Range | Step | Default ... Desc
|
|
* X.Flow [ml/min] | 0 - 9.999 | 0.001 | 0 ... Pump X flow rate (0: A, 1: B, 2: C)
|
|
* X.Pres [bar(1)*] | 0, 10 - 392 | 1 | 0 ... Pump X Pressure
|
|
* (1)* > Can be changed to kgf/cm³, psi, MPa, bar
|
|
* See Page 170 of Maual for more Details! */
|
|
struct LCPump
|
|
{
|
|
LCPump()
|
|
: actPressure(0), setFlow(0) {}
|
|
void pPressure(uint32_t press_int)
|
|
{actPressure = 10.962565204644875*exp(82.61694351137422 * (((float)press_int - 1093764743)/1e9));}
|
|
float actPressure;
|
|
float setFlow;
|
|
};
|
|
|
|
/* Combined status struct
|
|
* SIL Status, Status 1 and Status 2 Params
|
|
* The label lists contain the label for the corrosponding bit (1, 2, 4, 8 ...)
|
|
* Empty String means unknown
|
|
*/
|
|
struct Stats
|
|
{
|
|
uint32_t silst;
|
|
uint32_t status1;
|
|
uint32_t status2;
|
|
const QStringList silst_labels = {"INSTALED", "INJECT", "TRANSMIT", "RINSE", "?16", "ERROR", "STOP"};
|
|
const QStringList status1_labels = {"READY", "CTONOTREADY", "RUN", "PAUSE", "?16", "HOLD", "ERROR", "?128", "ACTIVATE", "?512", "?1024", "PURGE", "?4096", "?8192", "WAITCTO", "SLEEP", "WARNING", "?131072", "PUMPAON", "PUMPBON", "PUMPCON", "PUMPDON", "?4194304", "?8388608", "?16777216", "?33554432", "CTOAON", "CTOBON", "CTOCON", "CTODON"};
|
|
const QStringList status2_labels = {"PPURGING_A", "PPURGING_B", "PPURGING_C", "PPURGING_D", "?16", "PUMPON", "OVENON", "?128", "?256", "?512", "?1024", "?2048", "?4096", "?8192", "?16384", "?32768", "?65536", "?131072", "?262144", "INJECT_READY", "?1048576", "?2097152", "?4194304", "?8388608", "?16777216", "?33554432", "?67108864", "IPURGING_R0", "IPURGING_R1", "IPURGING_R2", "IPURGING_RNS", "IPURGING_INJ"};
|
|
};
|
|
|
|
/* Param [Unit] | Range | Step | Default ... Desc
|
|
* WAVE [nm] | 190 - 600 | 1 | 254 ... Wavelength 1 (D2)
|
|
* WAVE2 [nm] | 190 - 600 | 1 | 254 ... Wavelength 2 (D2)
|
|
* LAMP [1] | 0,1 | 1 | 254 ... Lamp (0: Off, 1: On) (D2)
|
|
* See Page 177 of Manual for more TODOs */
|
|
struct LCDetector
|
|
{
|
|
float waveLen1 = 0;
|
|
float waveLen2 = 0;
|
|
float lamp = 0;
|
|
};
|
|
|
|
struct LCAutosampler
|
|
{
|
|
float rack = 0;
|
|
};
|
|
|
|
struct LCStatus
|
|
{
|
|
LCStatus(){}
|
|
uint32_t time = 0;
|
|
uint16_t buf_wait[7]{};
|
|
LCPump pump[3]{};
|
|
LCDetector detector[2]{};
|
|
LCAutosampler autosampler{};
|
|
float totalFlow = 0; // Total flow rate in gradient pumping
|
|
uint num_pumps = 0; // Set by
|
|
uint num_detectors = 0;
|
|
Stats stats;
|
|
};
|
|
|
|
// Config struct - TODO: Catigorize compleatly!
|
|
struct LCconfiguration
|
|
{
|
|
QList<LCPort> pumps{};
|
|
QList<LCPort> detectors{};
|
|
QList<LCPort> other{};
|
|
void clear() {
|
|
pumps.clear();
|
|
detectors.clear();
|
|
other.clear();
|
|
}
|
|
|
|
// Options
|
|
quint8 AD1 = 0;
|
|
quint8 AD2 = 0;
|
|
// TODO: Implement the rest of the options
|
|
};
|
|
|
|
struct BufSt
|
|
{
|
|
quint8 curFlag = 0;
|
|
double curValue = 0.0;
|
|
quint16 period = 0;
|
|
float convFact = 0;
|
|
float gainFact = 0;
|
|
quint8 databuf[4]{};
|
|
QList<double> vals{};
|
|
};
|
|
|
|
class CmdVal : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
CmdVal(QString cmd, ShimLCCommandStack* cmdStack)
|
|
: cmd(cmd), cmdStack(cmdStack) {}
|
|
QByteArray set_value{};
|
|
QByteArray act_value{};
|
|
|
|
public slots:
|
|
void update()
|
|
{
|
|
updateSet();
|
|
updateAct();
|
|
}
|
|
void updateSet()
|
|
{
|
|
waitingForSet = 1;
|
|
idSet = cmdStack->getSetVal(cmd, &set_value);
|
|
connect(cmdStack, &ShimLCCommandStack::dataAvailable, this, &CmdVal::newData);
|
|
}
|
|
void updateAct()
|
|
{
|
|
waitingForAct = 1;
|
|
idAct = cmdStack->getActVal(cmd, &act_value);
|
|
connect(cmdStack, &ShimLCCommandStack::dataAvailable, this, &CmdVal::newData);
|
|
}
|
|
|
|
private slots:
|
|
void newData(uint32_t id)
|
|
{
|
|
if(id == idSet)
|
|
waitingForSet = 0;
|
|
if(id == idAct)
|
|
waitingForAct = 0;
|
|
if(!(waitingForAct | waitingForSet))
|
|
disconnect(cmdStack, &ShimLCCommandStack::dataAvailable, this, &CmdVal::newData);
|
|
}
|
|
|
|
signals:
|
|
void updated();
|
|
|
|
private:
|
|
QString cmd;
|
|
ShimLCCommandStack* cmdStack;
|
|
uint32_t idSet;
|
|
uint32_t idAct;
|
|
bool waitingForSet = 0;
|
|
bool waitingForAct = 0;
|
|
};
|
|
|
|
// ---
|
|
|
|
#define ID_CONF 0
|
|
#define ID_STATUS 1
|
|
#define ID_ENV 2
|
|
#define ID_CHK 3
|
|
#define ID_PIF 4
|
|
#define ID_BUF 4
|
|
|
|
class ShimLCController : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
void updateConfig();
|
|
void updateStatus();
|
|
void updateEnv();
|
|
void updateChk();
|
|
void updatePif();
|
|
void updateBuf();
|
|
void reconnect(QSettings *settings);
|
|
LCconfiguration configuration{};
|
|
LCStatus lastStatus{};
|
|
BufSt bufst[6]{};
|
|
|
|
explicit ShimLCController(QObject *parent = nullptr);
|
|
~ShimLCController();
|
|
|
|
signals:
|
|
void newConfigAv();
|
|
void newStatusAv();
|
|
void connectionStateChanged(QAbstractSocket::SocketState state);
|
|
void newDataAv();
|
|
|
|
private:
|
|
void parseLcnf(uint32_t idVal);
|
|
void parseStatus(uint32_t idVal);
|
|
void parseEnv(uint32_t idVal);
|
|
void parseChk(uint32_t idVal);
|
|
void parsePif(uint32_t idVal);
|
|
void parseLbuf(uint32_t idVal);
|
|
uint32_t ids[6]; // 0 - config / 1 - status / 2 - env / 3 - chk / 4 - PIF / 5 - BUF
|
|
ShimLCCommandStack cmd{};
|
|
QByteArray data{};
|
|
int cur_buf = 0;
|
|
};
|
|
|
|
#endif // SHIMLCCONTROLLER_H
|