#include "com.h" #include //#include "controlBus.h" ////////////////////////////////////////////////////////////////////////////////// /// /// serial hardware layer /// ////////////////////////////////////////////////////////////////////////////////// static int64_t com_want2read; // ------------------------------------------------------------------------------------------------------------- // --------- PUBLIC -------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- void T_com::writeToSerial(const QByteArray &data, uint16_t sendLength) { sendBuffer=data; sendLen=sendLength; if (CatSerial->isOpen()) { //qDebug() << "sending..." << sendBuffer; CatSerial->write(sendBuffer); } else qDebug() << "error sending, port is not open"; } bool T_com::readFromSerial(QByteArray &data, uint16_t &sendLength) { // return one time true if new data (completly) read. // return new data in &data and &sendLength to other objects uint16_t ll=rawInLen; if (!CatSerial->isOpen()) return false; data.clear(); data.append(rawInput); sendLength=ll; rawInLen=0; // beim 2. Aufruf 0 zurück weil nichts neues da if (ll>0) return true; return false; } // ------------------------------------------------------------------------------------------------------------- // --------- PRIVATES -------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- T_com::T_com(QObject *parent) : QObject(parent) { // port settings come from tabCom->Sdata->serial gpi_serialChanged(); CatSerial = new QSerialPort(); // PortHW object for Control&Analyse Tool //CatSerial->clear(); //CatSerial->clearError(); connect(CatSerial, &QSerialPort::readyRead, this, &T_com::readSomeBytes); // still reading, not sure if complete, undefined number of calls while reading connect(CatSerial, &QSerialPort::bytesWritten, this, &T_com::serialSendComplete); // system confirms sending complete //connect(CatSerial, &QSerialPort::dataTerminalReadyChanged, this, &T_com::incomingWake); //connect(CatSerial, &QSerialPort::requestToSendChanged, this, &T_com::incomingWake); // timer detects time gap in input flow serRecTime = new QTimer(); connect(serRecTime, SIGNAL(timeout()), this, SLOT(receiveTO())); serRecTime->setSingleShot(true); // single shot! only one impulse if receive complete serRecTime->stop(); // on hold // check COM-TAB periodic if user wants to connect or disconnect QTimer *ChkConnectTimer = new QTimer(); connect(ChkConnectTimer, SIGNAL(timeout()), this, SLOT(ser_ISR100ms())); ChkConnectTimer->setSingleShot(false); ChkConnectTimer->start(100); // in ms com_want2read=0; } T_com::~T_com() { if (CatSerial->isOpen()) CatSerial->close(); } void T_com::ser_ISR100ms() { // call every 100ms to check if user(HMI) wants to connect or disconnect //qDebug() << "~~>LIB" << "checking connect button... " ; uint8_t chkConn = gpi_getSerialConn(); // from global GUI buffer (Sdata) switch (chkConn) { case 0: // 0 button "connect" was just released closeSerialPort(); gpi_serialChanged(); // set chkConn to 2, thus getting edge break; case 1: // 1 button "connect" was just pressed open_Serial_Port(); gpi_serialChanged(); // set chkConn to 2, thus getting edge break; } if (CatSerial->isOpen()) gpi_serialIsOpen(true); else gpi_serialIsOpen(false); } // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- char T_com::open_Serial_Port() { bool ret; QString myString=nullptr, myPortName=nullptr, myBaudStr=nullptr; int myBaudNr; if (CatSerial->isOpen()) return 0; // opening twice is not allowed //qDebug() << "connecting..." << myPortName; myPortName=gpi_getComPortName(); // was selected and stored from GUI CatSerial->setPortName(myPortName); myBaudNr=gpi_getBaudNr(); // was selected and stored from GUI switch (myBaudNr) { // 0:1200 1:9600 2:19200 3:38400 4:57600 5:115200 case 0: CatSerial->setBaudRate(QSerialPort::Baud1200); myBaudStr="1200"; break; case 1: CatSerial->setBaudRate(QSerialPort::Baud9600); myBaudStr="9600"; break; case 2: CatSerial->setBaudRate(QSerialPort::Baud19200); myBaudStr="19200"; break; case 3: CatSerial->setBaudRate(QSerialPort::Baud38400); myBaudStr="38400"; break; case 4: CatSerial->setBaudRate(QSerialPort::Baud57600); myBaudStr="57600"; break; case 5: CatSerial->setBaudRate(QSerialPort::Baud115200); myBaudStr="115200"; break; } CatSerial->setDataBits(QSerialPort::Data8); // alt: QSerialPort::Data5,6,7,8 CatSerial->setParity(QSerialPort::NoParity); // alt: EvenParity, OddParity, NoParity CatSerial->setStopBits(QSerialPort::OneStop); // alternative: OneStop, TwoStop, OneAndHalfStop CatSerial->setFlowControl(QSerialPort::NoFlowControl); // alt: HardwareControl, SoftwareControl, NoFlowControl ret=CatSerial->open(QIODevice::ReadWrite); // alt: QIODevice::ReadWrite QIODevice::ReadOnly QIODevice::WriteOnly if (!ret) { myString.clear(); myString = "error "; myString.append(CatSerial->errorString()); qDebug() << myString; gpi_setTxt4comStateLine(myString); return 0; } else { myString.clear(); myString.append(myPortName); //lang=myString.size(); myString.append(" opened with "); myString.append(myBaudStr); myString.append(" 8N1"); qDebug() << myString; gpi_setTxt4comStateLine(myString); gpi_setTxt4RsDiagWin(myString+"\n"); } return 0; } void T_com::closeSerialPort() { if (CatSerial->isOpen()) { qDebug() << "closing connection"; CatSerial->close(); gpi_setTxt4comStateLine("closed"); gpi_setTxt4RsDiagWin("closed"); } } void T_com::readSomeBytes(void) { // called by serial-read-detection // restart off-time as input flow is ongoing // timer for slow receive // and serves as timeout for fast receive is msg is shorter as expected serRecTime->stop(); serRecTime->start(20); // in ms //qDebug()<< "com-rec read some bytes"; this->receiveByLength(); // since 14.12.21: fast receive } void T_com::receiveFixLen(int64_t nrOfbytesToReceive) { // call this before sending a request to slave // then we know exactly when reception is complete -> much faster com_want2read=nrOfbytesToReceive; // since 14.12.21: FastDevice Protocol has two lengthen: // fast: 12byte reception long: 68byte } void T_com::receiveByLength(void) { if (CatSerial->isOpen()) { QString myString=nullptr, tmpStr=nullptr; int64_t nrOfBytesreceived = CatSerial->bytesAvailable(); // nr of received bytes //qDebug()<< "com-rec current Len: "<< nrOfBytesreceived; if (nrOfBytesreceived >= com_want2read) { QByteArray data = CatSerial->readAll(); // erst auslesen wenn alles da! löscht den Empfangspuffer serRecTime->stop(); // stop timeout to avoid 2nd emit rawInLen=uint16_t (nrOfBytesreceived); rawInput.clear(); rawInput.append(data); //qDebug()<< "com-recFinished by Len "<< rawInLen; gpi_set2ndTxt4RsDiagWin(myString); // 4.10.23 hier neu emit receivingFinished(); } } } void T_com::receiveTO(void) { // no new input data for 20ms, --> assuming frame complete // save data in private "rawInput"-buffer if (CatSerial->isOpen()) { QString myString=nullptr, tmpStr=nullptr; int64_t nrOfBytesreceived = CatSerial->bytesAvailable(); // nr of received bytes QByteArray data = CatSerial->readAll(); rawInLen=uint16_t (nrOfBytesreceived); rawInput.clear(); rawInput.append(data); //rawInput[rawInLen]=0; // Zwangsterminierung bei QByteArray nicht nötig // diag display in serial in/out window and debug window myString.clear(); myString.setNum(rawInLen); myString.append(" in: "); //myString.append(rawInput); for (int ii=0; ii0x80 dann wird EIN Byte 16 stellig angezeigt int ll=tmpStr.length(); if (ll>2) { myString.append(tmpStr[ll-2]); myString.append(tmpStr[ll-1]); } else { myString.append(tmpStr); } myString.append(" "); } myString.append("\n"); #ifdef PRINTALLDEBUGS qDebug() << "VCP:" << myString; // display all inputs and outputs in output window #endif //gpi_setTxt4RsDiagWin(myString); gpi_set2ndTxt4RsDiagWin(myString); // 4.10.23: diese verwenden weil die gpi_setTxt4RsDiagWin() durch Ausgabe ueberschrieben wird //qDebug()<< "com-recFinished by TO"; emit receivingFinished(); } } void T_com::serialSendComplete(void) { // system confirms sending complete, diag display QString myString=nullptr, tmpStr=nullptr; myString.clear(); myString.setNum(sendLen); myString.append(" out: "); for (int ii=0; ii0x80 dann 16stellig int ll=tmpStr.length(); if (ll>2) { //qDebug() << "long_string" << ll << "\n"; myString.append(tmpStr[ll-2]); myString.append(tmpStr[ll-1]); } else { myString.append(tmpStr); } myString.append(" "); } #ifdef PRINTALLDEBUGS myString.append("\n"); qDebug() << myString; // display all output data in out-window #endif gpi_setTxt4RsDiagWin(myString); emit sendingFinished(); // for whom it may interest } bool T_com::isPortOpen(void) { if (CatSerial->isOpen()) return true; return false; } // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- /* uint8_t T_com::getAllPortPins(void) { uint8_t rs232pins=0; rs232pins= uint8_t(CatSerial->pinoutSignals()); // rs232pins: all signals bitwise coded in one byte: // readback output: bit 0=TxD(=output) bit2=DTR (=output) bit 6=RTS (=output) // unused inputs: bit1=RxD bit 3=DCD bit 5 = RING // handshake inputs: bit 4=DSR (0x10) bit 7=CTS (0x80) //qDebug()<<"serial port pins: " << rs232pins; return rs232pins; } bool T_com::getHSin_CTS(void) { // return the used Handshake IN (CTS, alt. DSR): true= high level (+8V) uint8_t rs232pins=0; rs232pins= uint8_t(CatSerial->pinoutSignals()); // rs232pins: all signals bitwise coded in one byte: // readback output: bit 0=TxD(=output) bit2=DTR (=output) bit 6=RTS (=output) // unused inputs: bit1=RxD bit 3=DCD bit 5 = RING // handshake inputs: bit 4=DSR (0x10) bit 7=CTS (0x80) if (rs232pins & 0x80) // CTS return true; return false; } bool T_com::getHSin_DSR(void) { uint8_t rs232pins=0; rs232pins= uint8_t(CatSerial->pinoutSignals()); if (rs232pins & 0x10) // DSR return true; return false; } void T_com::incomingWake(void) //(bool LevelOfTheBit) { emit wasWokenBySerialHandshake(); } bool T_com::setHSout_RTS(bool hsout) { // hsout true=positiv voltage +12V false= -12V // retval: true=setting OK bool cc; // 10.5.19, am Windows-PC nachgemessen, funktioniert gut // false ergibt -12V true ergibt +12V cc=CatSerial->setRequestToSend(hsout); // RTS out // retval true means "setting was successful" // alternative: use DTR as Handshake: //cc=CatSerial->setDataTerminalReady(false); // DTR out // retval true means "setting was successful" //qDebug()<<"RTS " <setDataTerminalReady(hsout); // DTR out // retval true means "setting was successful" //qDebug()<<"DTR " <