Page MenuHomec4science

hriboard.cpp
No OneTemporary

File Metadata

Created
Sat, Jul 5, 15:44

hriboard.cpp

#include "hriboard.h"
#include <QDebug>
#include <QSerialPortInfo>
#include <stdexcept>
const int SYNCVAR_LIST_ITEM_SIZE = SYNCVAR_NAME_SIZE + 3;
SyncVar::SyncVar(quint8 index, QString name, VarAccess access, int size)
: index(index), name(name), access(access), size(size)
{
}
SyncVar::~SyncVar()
{
}
void SyncVar::setValue(const QByteArray &newValue)
{
if(newValue.size() == getSize())
value = newValue;
else
throw std::runtime_error("SyncVar::setValue: wrong size.");
}
QByteArray SyncVar::getValue() const
{
return value;
}
quint8 SyncVar::getIndex() const
{
return index;
}
QString SyncVar::getName() const
{
return name;
}
int SyncVar::getSize() const
{
return size;
}
SyncVar* makeSyncVar(int index, QString name, VarType type, VarAccess access,
int size)
{
switch(type)
{
case BOOL: return new SyncVarT<uint8_t>(index, name, access, size);
case UINT8: return new SyncVarT<uint8_t>(index, name, access, size);
case INT8: return new SyncVarT<int8_t>(index, name, access, size);
case UINT16: return new SyncVarT<uint16_t>(index, name, access, size);
case INT16: return new SyncVarT<int16_t>(index, name, access, size);
case UINT32: return new SyncVarT<uint32_t>(index, name, access, size);
case INT32: return new SyncVarT<int32_t>(index, name, access, size);
case UINT64: return new SyncVarT<uint64_t>(index, name, access, size);
case INT64: return new SyncVarT<uint64_t>(index, name, access, size);
case FLOAT32: return new SyncVarT<float>(index, name, access, size);
case FLOAT64: return new SyncVarT<double>(index, name, access, size);
default: throw std::runtime_error("makeSyncVar(): bad type.");
}
}
HriBoard::HriBoard()
{
}
HriBoard::~HriBoard()
{
for(SyncVar* sv : streamedVars)
delete sv;
}
void HriBoard::openLink(QString comPortName)
{
streamID = 0;
// Setup the serial port.
serial.setPortName(comPortName);
serial.setBaudRate(UART_BAUDRATE);
serial.setDataBits(QSerialPort::Data8);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.setParity(QSerialPort::NoParity);
connect(&serial, SIGNAL(readyRead()), this, SLOT(onReceivedData()));
qDebug() << "Opening the serial COM port...";
if(serial.open(QIODevice::ReadWrite))
qDebug() << "COM port opened successfully.";
else
throw std::runtime_error("Can't open the COM port.");
// Stop the streaming, in case it was enabled.
QByteArray ba;
ba.append((char)0);
sendPacket(PC_MESSAGE_SET_STREAMED_VAR, ba);
// Request the variables list.
sendPacket(PC_MESSAGE_GET_VARS_LIST);
}
void HriBoard::setStreamedVars(QList<SyncVar const*> varsToStream)
{
// Copy the list of variables to stream, and compute the size of a streaming
// packet.
streamedVars.clear();
streamPacketSize = sizeof(quint8) + sizeof(quint32); // Stream ID + timestamp.
for(SyncVar const* sv : varsToStream)
{
streamedVars.append(syncVars[sv->getIndex()]);
streamPacketSize += sv->getSize();
}
//
streamID++;
QByteArray ba;
ba.append((quint8)varsToStream.size());
ba.append(streamID);
for(SyncVar const* sv : varsToStream)
{
int varIndex = sv->getIndex();
ba.append((quint8)varIndex);
}
sendPacket(PC_MESSAGE_SET_STREAMED_VAR, ba);
}
void HriBoard::setVar(const SyncVar *var, QByteArray value)
{
if(value.size() != var->getSize())
throw std::runtime_error("HriBoard::setVar(): bad value size.");
syncVars[var->getIndex()]->setValue(value);
QByteArray ba;
ba.append(var->getIndex());
ba.append(value);
sendPacket(PC_MESSAGE_SET_VAR, ba);
}
QStringList HriBoard::getComPorts()
{
QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
for(int i=ports.size()-1; i >= 0; i--)
{
// Remove from the list all the serial COM ports that are not the CP210x
// USB-to-serial chip.
if(!ports[i].description().contains("CP210x"))
ports.removeAt(i);
}
// Make a list of the COM ports names.
QStringList portsNames;
for(QSerialPortInfo comInfo : ports)
portsNames << comInfo.portName();
return portsNames;
}
void HriBoard::onReceivedData()
{
QByteArray rxData = serial.readAll();
//qDebug() << "RX:" << rxData;
for(int i=0; i<rxData.size(); i++)
{
quint8 rxByte = rxData[i];
if(rxByte & (1<<7)) // The start byte has the most significant bit high.
{
rxCurrentMessageType = (rxByte & ~(1<<7)); // Remove the start bit.
rxBytesCount = 0;
}
else // The data bytes have the most significant byte low.
rxBytesCount++;
if(rxBytesCount % 2 == 1) // First half of the data byte has been received.
firstHalfByte = rxByte; // Store it until the second half arrives.
else // Second half of the data byte has been received.
{
int dataBytesReady = rxBytesCount/2;
if(dataBytesReady > 0)
rxDataBytesBuffer[dataBytesReady-1] = (firstHalfByte<<4) + (rxByte & 0xf);
switch(rxCurrentMessageType)
{
case STM_MESSAGE_START_INFO:
if(dataBytesReady == 0)
{
// Request variables list.
sendPacket(PC_MESSAGE_GET_VARS_LIST);
}
break;
case STM_MESSAGE_VARS_LIST:
if(dataBytesReady >= 1)
{
quint8 nVars = rxDataBytesBuffer[0];
if(dataBytesReady == 1 + nVars * SYNCVAR_LIST_ITEM_SIZE)
{
for(SyncVar* sv : syncVars)
delete sv;
syncVars.clear();
QList<SyncVar const*> syncVarsConst;
quint8* p = &rxDataBytesBuffer[1];
for(int i=0; i<nVars; i++)
{
QString varName((char*)p);
p += SYNCVAR_NAME_SIZE;
VarType varType = (VarType)*p;
p++;
VarAccess varAccess = (VarAccess)*p;
p++;
int varSize = (int)*p;
p++;
SyncVar* sv = makeSyncVar(i, varName, varType,
varAccess, varSize);
syncVars.append(sv);
syncVarsConst.append(sv);
}
emit syncVarsListReceived(syncVarsConst);
}
}
break;
case STM_MESSAGE_STREAMING_PACKET:
if(dataBytesReady == streamPacketSize)
{
if(rxDataBytesBuffer[0] == (quint8)streamID)
{
// Decode the timestamp.
quint32 timestamp;
memcpy(&timestamp, &rxDataBytesBuffer[1],
sizeof(timestamp));
// Decode the variables values.
quint8 const* p = &rxDataBytesBuffer[5];
for(int i=0; i<streamedVars.size(); i++)
{
QByteArray value((char*)p,
streamedVars[i]->getSize());
streamedVars[i]->setValue(value);
p += streamedVars[i]->getSize();
}
emit syncVarsUpdated();
}
}
break;
case STM_MESSAGE_DEBUG_TEXT:
if(dataBytesReady > 0 &&
rxDataBytesBuffer[dataBytesReady-1] == '\0')
{
qDebug() << QString((const char*)rxDataBytesBuffer);
rxCurrentMessageType = 0;
}
break;
default: // Ignore.
break;
}
}
}
}
void HriBoard::sendPacket(quint8 messageType, QByteArray dataBytes)
{
QByteArray txBuffer;
txBuffer.append((1<<7) + messageType);
for(int i=0; i<dataBytes.size(); i++)
{
txBuffer.append(((quint8)dataBytes[i]) >> 4); // MSB.
txBuffer.append(((quint8)dataBytes[i]) & 0xf); // LSB.
}
serial.write(txBuffer);
serial.waitForBytesWritten(-1);
}

Event Timeline