/** Check if result is plausible. If it is, an ok is send and the command is stored in queue. If not, a resend and ok is send. */ void GCode::checkAndPushCommand() { if(hasM()) { if(M==110) // Reset line number { lastLineNumber = actLineNumber; Com::printFLN(Com::tOk); waitingForResend = -1; return; } if(M==112) // Emergency kill - freeze printer { Commands::emergencyStop(); } #ifdef DEBUG_COM_ERRORS if(M==666) { lastLineNumber++; return; } #endif // DEBUG_COM_ERRORS } if(hasN()) { if((((lastLineNumber+1) & 0xffff)!=(actLineNumber&0xffff))) { if(waitingForResend<0) // after a resend, we have to skip the garbage in buffers, no message for this { if(Printer::debugErrors()) { Com::printF(Com::tExpectedLine,lastLineNumber+1); Com::printFLN(Com::tGot,actLineNumber); } requestResend(); // Line missing, force resend } else { --waitingForResend; commandsReceivingWritePosition = 0; Com::printFLN(Com::tSkip,actLineNumber); Com::printFLN(Com::tOk); } return; } lastLineNumber = actLineNumber; } pushCommand(); #ifdef ACK_WITH_LINENUMBER Com::printFLN(Com::tOkSpace,actLineNumber); #else Com::printFLN(Com::tOk); #endif wasLastCommandReceivedAsBinary = sendAsBinary; waitingForResend = -1; // everything is ok. }
/* Start updating. Implementation of VariableNameManager's virtual funtion to establish a connection to a PV as the variable name has changed. This function may also be used to initiate updates when loaded as a plugin. */ void QELineEdit::establishConnection( unsigned int variableIndex ) { // Create a connection. // If successfull, the QCaObject object that will supply data update signals will be returned qcaobject::QCaObject* qca = createConnection( variableIndex ); // If a QCaObject object is now available to supply data update signals, connect it to the appropriate slots if( qca ) { QObject::connect( qca, SIGNAL( stringChanged( const QString&, QCaAlarmInfo&, QCaDateTime&, const unsigned int& ) ), this, SLOT( setTextIfNoFocus( const QString&, QCaAlarmInfo&, QCaDateTime&, const unsigned int& ) ) ); QObject::connect( qca, SIGNAL( connectionChanged( QCaConnectionInfo& ) ), this, SLOT( connectionChanged( QCaConnectionInfo& ) ) ); QObject::connect( this, SIGNAL( requestResend() ), qca, SLOT( resendLastData() ) ); } }
/* Start updating. Implementation of VariableNameManager's virtual funtion to establish a connection to a PV as the variable name has changed. This function may also be used to initiate updates when loaded as a plugin. */ void QEPeriodic::establishConnection( unsigned int variableIndex ) { // Create a connection. // If successfull, the QCaObject object that will supply data update signals will be returned qcaobject::QCaObject* qca = createConnection( variableIndex ); // If a QCaObject object is now available to supply data update signals, connect it to the appropriate slots if( qca ) { QObject::connect( qca, SIGNAL( floatingChanged( const double&, QCaAlarmInfo&, QCaDateTime&, const unsigned int& ) ), this, SLOT( setElement( const double&, QCaAlarmInfo&, QCaDateTime&, const unsigned int& ) ) ); // Get conection status changes always (subscribing or not) QObject::connect( qca, SIGNAL( connectionChanged( QCaConnectionInfo&, const unsigned int& ) ), this, SLOT( connectionChanged( QCaConnectionInfo&, const unsigned int& ) ) ); QObject::connect( this, SIGNAL( requestResend() ), qca, SLOT( resendLastData() ) ); } }
void DtmfDataLinkLayer::checkFrameReceiveList() { //initialize variable to hold EOT, goes and nogoes int request = 0; int listLength = 0; //iterate through list to find list length for(int i=0;i<8;i++) if(frameRecList[i].eot == 1) listLength = i+1; #ifdef DEBUG DEBUG_OUT << "Checking list of " << listLength << " entries..." << std::endl; for(int i=0;i<listLength;i++) { DEBUG_OUT << i << " - "; for(int j=7;j>=0;j--) DEBUG_OUT << (bool)(frameRecList[i].dataByte&(1<<j)); if(frameRecList[i].flag==1) DEBUG_OUT << " - received"; else DEBUG_OUT << " - missing"; if(frameRecList[i].eot == 1) DEBUG_OUT << " - End of transmission"; DEBUG_OUT << std::endl; } #endif //iterate through list and and set request variable according to flagbits for(int j=0;j<listLength;j++) { for(int i=0;i<j+1;i++) request |= ((bool)(frameRecList[i].flag)<<i); } //pass upwards if list is complete if(request == (pow(2.,listLength)-1) && listLength > 0) passDataUpwards(listLength); else //request resends requestResend(request); }
/** \brief Read from serial console or sdcard. This function is the main function to read the commands from serial console or from sdcard. It must be called frequently to empty the incoming buffer. */ void GCode::readFromSerial() { if(bufferLength>=GCODE_BUFFER_SIZE) return; // all buffers full if(waitUntilAllCommandsAreParsed && bufferLength) return; waitUntilAllCommandsAreParsed=false; millis_t time = HAL::timeInMilliseconds(); if(!HAL::serialByteAvailable()) { if((waitingForResend>=0 || commandsReceivingWritePosition>0) && time-timeOfLastDataPacket>200) { requestResend(); // Something is wrong, a started line was not continued in the last second timeOfLastDataPacket = time; } #ifdef WAITING_IDENTIFIER else if(bufferLength == 0 && time-timeOfLastDataPacket>1000) // Don't do it if buffer is not empty. It may be a slow executing command. { #if !SUPPORT_CURA Com::printFLN(Com::tWait); // Unblock communication in case the last ok was not received correct. #endif // !SUPPORT_CURA timeOfLastDataPacket = time; } #endif } while(HAL::serialByteAvailable() && commandsReceivingWritePosition < MAX_CMD_SIZE) // consume data until no data or buffer full { #if FEATURE_WATCHDOG HAL::pingWatchdog(); #endif // FEATURE_WATCHDOG timeOfLastDataPacket = time; //HAL::timeInMilliseconds(); commandReceiving[commandsReceivingWritePosition++] = HAL::serialReadByte(); // first lets detect, if we got an old type ascii command if(commandsReceivingWritePosition==1) { if(waitingForResend>=0 && wasLastCommandReceivedAsBinary) { if(!commandReceiving[0]) waitingForResend--; // Skip 30 zeros to get in sync else waitingForResend = 30; commandsReceivingWritePosition = 0; continue; } if(!commandReceiving[0]) // Ignore zeros { commandsReceivingWritePosition = 0; continue; } sendAsBinary = (commandReceiving[0] & 128)!=0; } if(sendAsBinary) { if(commandsReceivingWritePosition < 2 ) continue; if(commandsReceivingWritePosition == 5 || commandsReceivingWritePosition == 4) binaryCommandSize = computeBinarySize((char*)commandReceiving); if(commandsReceivingWritePosition == binaryCommandSize) { GCode *act = &commandsBuffered[bufferWriteIndex]; if(act->parseBinary(commandReceiving,true)) // Success act->checkAndPushCommand(); else requestResend(); commandsReceivingWritePosition = 0; return; } } else // Ascii command { char ch = commandReceiving[commandsReceivingWritePosition-1]; if(ch == 0 || ch == '\n' || ch == '\r' || (!commentDetected && ch == ':')) // complete line read { //Com::printF(PSTR("Parse ascii"));Com::print((char*)commandReceiving);Com::println(); commandReceiving[commandsReceivingWritePosition-1]=0; commentDetected = false; if(commandsReceivingWritePosition==1) // empty line ignore { commandsReceivingWritePosition = 0; continue; } GCode *act = &commandsBuffered[bufferWriteIndex]; if(act->parseAscii((char *)commandReceiving,true)) // Success act->checkAndPushCommand(); else requestResend(); commandsReceivingWritePosition = 0; return; } else { if(ch == ';') commentDetected = true; // ignore new data until lineend if(commentDetected) commandsReceivingWritePosition--; } } if(commandsReceivingWritePosition == MAX_CMD_SIZE) { requestResend(); return; } } #if SDSUPPORT if(!sd.sdmode || commandsReceivingWritePosition!=0) // not reading or incoming serial command return; while( sd.filesize > sd.sdpos && commandsReceivingWritePosition < MAX_CMD_SIZE) // consume data until no data or buffer full { #if FEATURE_WATCHDOG HAL::pingWatchdog(); #endif // FEATURE_WATCHDOG timeOfLastDataPacket = HAL::timeInMilliseconds(); int n = sd.file.read(); #if FEATURE_WATCHDOG HAL::pingWatchdog(); #endif // FEATURE_WATCHDOG if(n==-1) { Com::printFLN(Com::tSDReadError); UI_ERROR("SD Read Error"); // Second try in case of recoverable errors sd.file.seekSet(sd.sdpos); n = sd.file.read(); #if FEATURE_WATCHDOG HAL::pingWatchdog(); #endif // FEATURE_WATCHDOG if(n==-1) { Com::printErrorFLN(PSTR("SD error did not recover!")); sd.sdmode = false; break; } UI_ERROR("SD error fixed"); } sd.sdpos++; // = file.curPosition(); commandReceiving[commandsReceivingWritePosition++] = (uint8_t)n; // first lets detect, if we got an old type ascii command if(commandsReceivingWritePosition==1) { sendAsBinary = (commandReceiving[0] & 128)!=0; } if(sendAsBinary) { if(commandsReceivingWritePosition < 2 ) continue; if(commandsReceivingWritePosition == 4 || commandsReceivingWritePosition == 5) binaryCommandSize = computeBinarySize((char*)commandReceiving); if(commandsReceivingWritePosition==binaryCommandSize) { GCode *act = &commandsBuffered[bufferWriteIndex]; if(act->parseBinary(commandReceiving,false)) // Success, silently ignore illegal commands pushCommand(); commandsReceivingWritePosition = 0; return; } } else { char ch = commandReceiving[commandsReceivingWritePosition-1]; bool returnChar = ch == '\n' || ch == '\r'; if(returnChar || sd.filesize == sd.sdpos || (!commentDetected && ch == ':') || commandsReceivingWritePosition >= (MAX_CMD_SIZE - 1) ) // complete line read { if(returnChar || ch == ':') commandReceiving[commandsReceivingWritePosition-1]=0; else commandReceiving[commandsReceivingWritePosition]=0; commentDetected = false; if(commandsReceivingWritePosition==1) // empty line ignore { commandsReceivingWritePosition = 0; continue; } GCode *act = &commandsBuffered[bufferWriteIndex]; if(act->parseAscii((char *)commandReceiving,false)) // Success pushCommand(); commandsReceivingWritePosition = 0; return; } else { if(ch == ';') commentDetected = true; // ignore new data until lineend if(commentDetected) commandsReceivingWritePosition--; } } } sd.sdmode = false; Com::printFLN(Com::tDonePrinting); commandsReceivingWritePosition = 0; commentDetected = false; Printer::setMenuMode(MENU_MODE_SD_PRINTING,false); BEEP_STOP_PRINTING #endif }
// Parse and use an XML string representing the widget's user info. // The user info includes attributes for each element in the table such as // if the element is selectable, and what the user defined values are for an element. void QEPeriodic::setUserInfo( QString inStr ) { QXmlStreamReader xml( inStr ); // Set all element info to default as only non default is saved in the XML for( int i = 0; i < NUM_ELEMENTS; i++ ) { userInfo[i].enable = false; userInfo[i].value1 = 0.0; userInfo[i].value2 = 0.0; userInfo[i].elementText.clear(); } // Step over initial document start if( xml.readNext() == QXmlStreamReader::StartDocument ) { // Parse all elements while (!xml.atEnd()) { // Ignore all but 'elements' elements if( xml.readNext() == QXmlStreamReader::StartElement && xml.name().compare( "elements" ) == 0 ) { // Found an 'elements' element // Parse all elements in the 'elements' element while (!xml.atEnd()) { // Ignore all but 'element' elements if( xml.readNext() == QXmlStreamReader::StartElement && xml.name().compare( "element" ) == 0 ) { // Found an 'element' element, get any attributes bool ok; QXmlStreamAttributes attributes = xml.attributes(); // Only use the element if it includes a valid element number attribute int i = attributes.value( "number" ).toString().toInt( &ok ); if( i >= 1 && i <= NUM_ELEMENTS ) { // Element number is good, so extract any other attributes. // Note, the presence of each attribute is not checked. // If not present or valid then the returned 0.0 or empty strings are used i--; if( attributes.value( "enable" ).toString().compare( "yes" ) == 0 ) userInfo[i].enable = true; else userInfo[i].enable = false; userInfo[i].value1 = attributes.value( "value1" ).toString().toDouble( &ok ); userInfo[i].value2 = attributes.value( "value2" ).toString().toDouble( &ok ); userInfo[i].elementText = attributes.value( "text" ).toString(); } } } } } } // if (xml.hasError()) { // qDebug() << xml.errorString(); // } emit requestResend(); }
// variable 2 tolerance void QEPeriodic::setVariableTolerance2( double variableTolerance2In ) { variableTolerance2 = variableTolerance2In; emit requestResend(); }
// variable 2 type void QEPeriodic::setVariableType2( variableTypes variableType2In ) { variableType2 = variableType2In; emit requestResend(); }
// presentation options void QEPeriodic::setPresentationOption( presentationOptions presentationOptionIn ) { presentationOption = presentationOptionIn; updatePresentationOptions(); emit requestResend(); }
// subscribe void QEPeriodic::setSubscribe( bool subscribeIn ) { subscribe = subscribeIn; emit requestResend(); }
/** Check if result is plausible. If it is, an ok is send and the command is stored in queue. If not, a resend and ok is send. */ void GCode::checkAndPushCommand() { if(hasM()) { if(M == 110) // Reset line number { lastLineNumber = actLineNumber; Com::printFLN(Com::tOk); waitingForResend = -1; return; } if(M == 112) // Emergency kill - freeze printer { Commands::emergencyStop(); } #ifdef DEBUG_COM_ERRORS if(M == 666) // force an communication error { lastLineNumber++; return; } else if(M == 668) { lastLineNumber = 0; // simulate a reset so lines are out of resend buffer } #endif // DEBUG_COM_ERRORS } if(hasN()) { if((((lastLineNumber + 1) & 0xffff) != (actLineNumber & 0xffff))) { if(static_cast<uint16_t>(lastLineNumber - actLineNumber) < 40) { // we have seen that line already. So we assume it is a repeated resend and we ignore it commandsReceivingWritePosition = 0; Com::printFLN(Com::tSkip,actLineNumber); Com::printFLN(Com::tOk); } else if(waitingForResend < 0) // after a resend, we have to skip the garbage in buffers, no message for this { if(Printer::debugErrors()) { Com::printF(Com::tExpectedLine, lastLineNumber + 1); Com::printFLN(Com::tGot, actLineNumber); } requestResend(); // Line missing, force resend } else { --waitingForResend; commandsReceivingWritePosition = 0; Com::printFLN(Com::tSkip, actLineNumber); Com::printFLN(Com::tOk); } return; } lastLineNumber = actLineNumber; } /* This test is not compatible with all hosts. Replaced by forbidding backward switch of protocols. else if(lastLineNumber && !(hasM() && M == 117)) { // once line number always line number! if(Printer::debugErrors()) { Com::printErrorFLN(PSTR("Missing linenumber")); } requestResend(); return; }*/ if(GCode::hasFatalError() && !(hasM() && M==999)) { GCode::reportFatalError(); } else { pushCommand(); } #ifdef DEBUG_COM_ERRORS if(hasM() && M == 667) return; // omit ok #endif #if ACK_WITH_LINENUMBER Com::printFLN(Com::tOkSpace, actLineNumber); #else Com::printFLN(Com::tOk); #endif wasLastCommandReceivedAsBinary = sendAsBinary; keepAlive(NotBusy); waitingForResend = -1; // everything is ok. }