void onCommandLoopInterval()
{
	int loopInterval = convertToInt(gParameters[0]);

	if (isReadCommand(gParameters[0]))
	{
		sendInt(pidLoopInterval);
		sendAck();
	}
	else if (isIntWithinRange(loopInterval, PID_INTERVAL_MS_MIN, PID_INTERVAL_MS_MAX))
	{
		if (!isPidEnabled)
		{
			pidLoopInterval = loopInterval;
			sendAck();
		}
		else
		{
			Serial.println(F("Cannot change loop interval while PID control is on."));
			sendNack();
		}
	}
	else
	{
		sendIntRangeError(PID_INTERVAL_MS_MIN, PID_INTERVAL_MS_MAX, MILLISECONDS_UNIT);
	}
}
void onCommandSetPoint()
{
	if (isChannelCorrect(gParameters[0]))
	{
		int channel = convertToInt(gParameters[0]);
		double setPoint = atof(gParameters[1]);

		if (isReadCommand(gParameters[1]))
		{
			sendDouble(setPoints[channel]);
			sendAck();
		}
		else if (isDoubleWithinRange(setPoint, minSetPoint[channel], maxSetPoint[channel]))
		{
			setPoints[channel] = setPoint;
			sendAck();
		}
		else
		{
			sendDoubleRangeError(minSetPoint[channel], maxSetPoint[channel], DEGREES_UNIT);
		}
	}
	else
	{
		sendChannelError();
	}
}
void onCommandRateLimit()
{
	if (isChannelCorrect(gParameters[0]))
	{
		int channel = convertToInt(gParameters[0]);
		int rateLimit = convertToInt(gParameters[1]);

		if (isReadCommand(gParameters[1]))
		{
			sendInt(outputRateLimits[channel]);
			sendAck();
		}
		else if (isIntWithinRange(rateLimit, OUTPUT_RATE_LIMIT_MIN, OUTPUT_RATE_LIMIT_MAX))
		{
			outputRateLimits[channel] = rateLimit;
			sendAck();
		}
		else
		{
			sendIntRangeError(OUTPUT_RATE_LIMIT_MIN, OUTPUT_RATE_LIMIT_MAX, DEGREES_UNIT);
		}
	}
	else
	{
		sendChannelError();
	}
}
void onCommandIntegralWindup()
{
	if (isChannelCorrect(gParameters[0]))
	{
		int channel = convertToInt(gParameters[0]);
		double windup = atof(gParameters[1]);

		if (isReadCommand(gParameters[1]))
		{
			sendDouble(iWindupThresholds[channel]);
			sendAck();
		}
		else if (isDoubleWithinRange(windup, I_WINDUP_THRESH_MIN, I_WINDUP_THRESH_MAX))
		{
			iWindupThresholds[channel] = windup;
			sendAck();
		}
		else
		{
			sendDoubleRangeError(I_WINDUP_THRESH_MIN, I_WINDUP_THRESH_MAX, DEGREES_UNIT);
		}
	}
	else
	{
		sendChannelError();
	}
}
void onCommandPidControl()
{
	if (isReadCommand(gParameters[0]))
	{
		sendOnOffStatus(isPidEnabled);
		sendAck();
	}
	else if (isOnCommandArg(gParameters[0]))
	{
		if (!isPidEnabled)
		{
			enablePid();
			sendAck();
		}
		else
		{
			Serial.println(F("PID control is already on."));
			sendNack();
		}
	}
	else if (isOffCommandArg(gParameters[0]))
	{
		disablePid();
		sendAck();
	}
	else
	{
		sendOnOffError();
	}
}
// Allows the reading or changing of direction for specified motor, but only allows change in
// direction if the change results in a percentage change of less than the outputRateLimit
void onCommandDirection()
{
	if (isChannelCorrect(gParameters[0]))
	{
		uint8_t channel = convertToInt(gParameters[0]);

		if (isReadCommand(gParameters[1]))
		{
			sendDirectionStatus(directions[channel]);
			sendAck();
		}
		else if (!isPidEnabled)
		{
			int output = currentOutputs[channel];
			int outputRateLimit = outputRateLimits[channel];
			Direction direction;

			if (isClockwiseCommandArg(gParameters[1]))
			{
				direction = Direction::Clockwise;
			}
			else if (isCounterClockwiseCommandArg(gParameters[1]))
			{
				direction = Direction::CounterClockwise;
			}
			else
			{
				sendDirectionError();
				return;
			}

			if (direction != directions[channel] && output > outputRateLimit / 2)
			{
				Serial << F("Cannot make a change to output by more than ") << outputRateLimit << F("%") << NEWLINE;
				sendNack();
			}
			else
			{
				applyMotorOutputs(channel, direction, output);
				sendAck();
			}
		}
		else
		{
			Serial.println(F("Cannot change direction while PID control is on."));
			sendNack();
		}
	}
	else
	{
		sendChannelError();
	}
}
void onCommandMotorDriver()
{
	if (isChannelCorrect(gParameters[0]))
	{
		uint8_t channel = convertToInt(gParameters[0]);

		if (isReadCommand(gParameters[1]))
		{
			sendMotorDriverStatus(motorDriverTypes[channel]);
			sendAck();
		}
		else
		{
			if (!isPidEnabled)
			{
				if (isAnalogVoltageCommandArg(gParameters[1]))
				{
					motorDriverTypes[channel] = AnalogVoltage;
					sendAck();
				}
				else if (isFrequencyCommandArg(gParameters[1]))
				{
					if (channel == TILT_CHANNEL)
					{
						motorDriverTypes[channel] = Frequency;
						sendAck();
					}
					else
					{
						Serial.println(F("Yaw (Channel 1) can only be set to Analog Voltage"));
						sendNack();
					}
				}
				else
				{
					sendMotorDriverError();
				}
			}
			else
			{
				Serial.println(F("Cannot change driver type while PID control is on."));
				sendNack();
			}
		}
	}
	else
	{
		sendChannelError();
	}
}
	void Receiver::handleMsg(Msg* msg) {
		// ACK package
		int sequenceNumber = msg->sequenceNumber;
		int windowEnd = (windowOrigin + sequenceSeed) % SEQUENCE_RANGE + WINDOW_SIZE;


		if (msg->sequenceNumber == (sequenceSeed + 1) % SEQUENCE_RANGE && msg->type == RESP_ERR && strcmp(msg->buffer, "NSF") == 0) {
			sendAck(sequenceNumber);
			throw std::exception("No such file.");
		}

		// Handle EOF
		if (isEofMsg(msg)) {
			int expectedSize;
			memcpy(&expectedSize, msg->buffer + 4, sizeof(expectedSize));
			if (expectedSize == totalPayloadSize) {
				windowOrigin++;
				isComplete = true;
				sendAck(sequenceNumber);
			}

			return;
		}

		sendAck(sequenceNumber);
		if (!isSequenceNumberInWindow(sequenceNumber))
			return;

		// Register package in buffer
		if (currentWindow[sequenceNumber] != NULL)
			return;

		int currentPayloadLength = msg->length;
		char* currentData = new char[currentPayloadLength];
		memcpy(currentData, msg->buffer, currentPayloadLength);

		Payload* currentPayload = new Payload();
		currentPayload->length = currentPayloadLength;
		currentPayload->data = currentData;
		currentWindow[sequenceNumber] = currentPayload;
		totalPayloadSize += currentPayloadLength; // It doesn't matter if it's out of order.

		// Normalize buffer
		int currentSequence = (windowOrigin + sequenceSeed) % SEQUENCE_RANGE;
		while (currentWindow[currentSequence] != NULL) {
			completedSet.push(currentWindow[currentSequence]);
			currentWindow[currentSequence] = NULL;
			currentSequence = (++windowOrigin + sequenceSeed) % SEQUENCE_RANGE;
		}
	}
Beispiel #9
0
/**
"SC" — Stepper and Servo Mode Configure

Command: SC,value1,value2<CR>
Response: OK<NL><CR>
Firmware versions: All
Execution: Immediate
Arguments:
value1 is an integer in the range from 0 to 255, which specifies the parameter
that you are adjusting.
value2 is an integer in the range from 0 to 65535. It specifies the value of the
parameter given by value1.
See the list of these parameters (value1) and allowed values (value2), below.
Description:00
This command allows you to configure the motor control modes that the EBB uses,
including parameters of the servo or solenoid motor used for raising and
lowering the pen, and how the stepper motor driver signals are directed.

The set of parameters and their allowed values is as follows:

SC,1,value2 Pen lift mechanism. value2 may be 0, 1 or 2. Early EggBot models
used a small solenoid, driven from an output signal on pin RB4.
SC,1,0 Enable only the solenoid output (RB4) for pen up/down movement.
SC,1,1 Enable only the RC servo output (RB1) for pen up/down movement.
SC,1,2 Enable both the solenoid (RB4) and RC servo (RB1) outputs for pen up/down
movement (default)
SC,2,value2 Stepper signal control. value2 may be 0, 1 or 2.
SC,2,0 Use microcontroller to control on-board stepper driver chips (default)
SC,2,1 Disconnect microcontroller from the on-board stepper motor drivers and
drive external step/direction motor drivers instead. In this mode, you can use
the microcontroller to control external step/direction drivers based on the
following pin assignments:
ENABLE1: RD1
ENABLE2: RA1
STEP1: RC6
DIR1: RC2
STEP2: RA5
DIR2: RA2
Note also that in this mode, you can externally drive the step/direction/enable
lines of the on board stepper motor drivers from the pins of J4 and J5. (Please
refer to the schematic for where these pins are broken out.)
SC,2,2 Disconnect microcontroller from both the built-in motor drivers and
external pins. All step/dir/enable pins on the PIC are set to inputs. This
allows you to control the on-board stepper motor driver chips externally with
your own step/dir/enable signals. Use the pins listed in the schematic from J5
and J4.
SC,4,servo_min Set the minimum value for the RC servo output position. servo_min
may be in the range 1 to 65535, in units of 83 ns intervals. This sets the "Pen
Up" position.
Default: 12000 (1.0 ms) on reset.
SC,5,servo_max Set the maximum value for the RC servo output position. servo_max
may be in the range 1 to 65535, in units of 83 ns intervals. This sets the "Pen
Down" position.
Default: 16000 (1.33 ms) on reset.
SC,8,maximum_S2_channels Sets the number of RC servo PWM channels, each of
S2_channel_duration_ms before cycling back to channel 1 for S2 command. Values
from 1 to 24 are valid for maximum_S2_channels.
Default: 8 on reset.
SC,9,S2_channel_duration_ms Set the number of milliseconds before firing the
next enabled channel for the S2 command. Values from 1 to 6 are valid for
S2_channel_duration_ms.
Default: 3 ms on reset.
SC,10,servo_rate Set rate of change of the servo position, for both raising and
lowering movements. Same units as rate parameter in S2 command.
SC,11,servo_rate_up Set the rate of change of the servo when going up. Same
units as rate parameter in S2 command.
SC,12,servo_rate_down Set the rate of change of the servo when going down. Same
units as rate parameter in S2 command.
SC,13,use_alt_pause - turns on (1) or off (0) alternate pause button function on
RB0. On by default. For EBB v1.1 boards, it uses RB2 instead.
Example: SC,4,8000\r Set the pen-up position to give a servo output of 8000,
about 0.66 ms.
Example: SC,1,1\r Enable only the RC servo for pen lift; disable solenoid
control output.
*/
void EBBParser::parseSC(const char* arg1, const char* arg2)
{
    if (arg1 == NULL || arg2 == NULL) {
        sendError();
        return;
    }

    int cmd = atoi(arg1);
    int value = atoi(arg2);
    switch (cmd) {
    case 4:
        setPenUpPos(value / 240 - 25);
        break;
    case 5:
        setPenDownPos(value / 240 - 25);
        break;
    case 6: // rotMin=value;    ignored
        break;
    case 7: // rotMax=value;    ignored
        break;
    case 11:
        setServoRateUp(value / 5);
        break;
    case 12:
        setServoRateDown(value / 5);
        break;
    default:
        sendError();
        return;
    }
    sendAck();
}
Beispiel #10
0
void playSolitaire(void *client) {

  // initialize
  deal_t *deal = newDeal(deck);

  play_t play;
  int status = SUCCESS;
  while (1) {
    putArena(arena);
    printf("\n");
    putDeal(deal);
    printf("\nEnter your play: ");
    getNextPlay(client,&play,deck);
    switch (play.type) {
    case ARENA_PLAY:
      // Play a card into the arena.
      status = makeArenaPlay(play.from,arena);
      break;
    case KING_PLAY:
      // Move a king card onto an empty lain stack.
      status = moveKingOntoFree(play.from,deal);
      break;
    case MOVE_PLAY:
      // Move a card (possibly with cards above it) onto some lain stack. 
      status = moveCardOntoAnother(play.from,play.onto);
      break;
    case DRAW_PLAY:
      // Draws the next card and puts it on top of the discard pile.
      status = pullFromDrawPile(deal);
      break;
    }
    
    sendAck(client,status);
  }
}
Beispiel #11
0
/**
 * Recieves a datapacket, sends it to the correct app
 * @param recvd   Recieved packet
 * @param datalen Length of recieved data
 * @param srcmip  Source MIP of packet
 */
void recvData(struct tp_packet *recvd, uint16_t datalen, uint8_t srcmip) {
	//if(debug) fprintf(stderr, "MIPTP: recvData(%p, %d, %d)\n", recvd, datalen, srcmip);
	struct applist *app = NULL;
	getApp(recvd->port, &app, approot);

	if(debug || seqnodb) fprintf(stderr, "MIPTP: Recieved data with len %d and SN %d from MIP %d to port %d.", datalen, recvd->seqno, srcmip, recvd->port);
	if(debug || seqnodb) {
		if(app == NULL) fprintf(stderr, " No app on that port\n");
		else fprintf(stderr, "\n");
	}
	if(app == NULL) return;

	if(recvd->seqno == app->recvinfo->nextRecvSeqno) {
		// Accept packet
		app->recvinfo->nextRecvSeqno++;
		addPacket(recvd, srcmip, datalen, app->recvinfo->recvQueue);

		while(containsSeqno(app->recvinfo->nextRecvSeqno, app->recvinfo->recvQueue))
			app->recvinfo->nextRecvSeqno++;

		if(debug) fprintf(stderr, "MIPTP: Packet accepted, now waiting for SN %d\n", app->recvinfo->nextRecvSeqno);
	} else if(recvd->seqno > app->recvinfo->nextRecvSeqno) {
		// Queue packet while waiting for a lost one
		addPacket(recvd, srcmip, datalen, app->recvinfo->recvQueue);
		if(debug) fprintf(stderr, "MIPTP: Packet buffered, still waiting for SN %d\n", app->recvinfo->nextRecvSeqno);
	}

	if(app->lastTimeout != 0) app->lastTimeout = 0;

	//fprintf(stderr, "MIPTP: R-DAT %d FROM %d\n", recvd->seqno, srcmip);

	sendAck(app, recvd->port, srcmip);
}
bufferStruct receiveSendData(bufferStruct buffer){
	bufferStruct result;
	if(getAck(buffer.bufferLength, buffer.buffer) & NEED_ACK > 0){
		#if STATE_UART_DEBUG >= 2
			uart_putstr ("seAck\r\n");
		#endif
		state = STATE_SENDING_ACK;
		
		backupData.bufferLength = buffer.bufferLength;
		memcpy(backupData.buffer, buffer.buffer, buffer.bufferLength);
		
		sendAck(buffer);
	} else {
		result.bufferLength = getPayloadLength(buffer.bufferLength, buffer.buffer);
		memcpy(result.buffer, getPayload(buffer.bufferLength, buffer.buffer), result.bufferLength);
		
		#if STATE_UART_DEBUG >= 3
		uart_putc('%');
		uart_putc(result.bufferLength);
		uart_putc('%');
		for(uint8_t i = 0; i < result.bufferLength; ++i){
			uart_putc(result.buffer[i]);
		}
		uart_putc('%');
		#endif
	}	
	return result;
}
// This command is complex because it only allows setting of frequency for channel 1
// This is because only the tilt motor can be controlled by frequency
void onCommandFrequencyOutput()
{
	if (isChannelCorrect(gParameters[0]))
	{
		uint8_t channel = convertToInt(gParameters[0]);
		uint16_t frequency = convertToUint(gParameters[1]);

		if (channel == TILT_CHANNEL)
		{
			if (isReadCommand(gParameters[1]))
			{
				sendInt(currentFrequency);
				sendAck();
			}
			else
			{
				if (!isSafetyOn)
				{
					if (isIntWithinRange(frequency, MOTOR_MIN_FREQUENCY, MOTOR_MAX_FREQUENCY))
					{
						setFrequency(frequency);
						sendAck();
					}
					else
					{
						sendIntRangeError(MOTOR_MIN_FREQUENCY, MOTOR_MAX_FREQUENCY, HERTZ_UNIT);
					}
				}
				else
				{
					Serial.println(F("Cannot change frequency output while safety is on."));
					sendNack();
				}
			}
		}
		else
		{
			Serial.println(F("Changing or reading of frequency only applies to channel 1"));
			sendNack();
		}
	}
	else
	{
		sendChannelError();
	}
}
Beispiel #14
0
/**
"TP" — Toggle Pen

Command: TP[,duration]<CR>
Response: OK<NL><CR>
Firmware versions: v1.9 and newer
Execution: Immediate
Arguments:
duration: (Optional) an integer in the range of 1 to 65535, giving an delay in
milliseconds.
Description:
This command toggles the state of the pen (up->down and down->up). EBB firmware
resets with pen in 'up' (servo_min) state.

Note that conventionally, we have used the servo_min ("SC,4") value as the 'Pen
up position', and the servo_max ("SC,5") value as the 'Pen down position'.

The optional duration argument is in milliseconds. It represents the total
length of time between when the pen move is started, and when the next command
will be executed. Note that this is not related to how fast the pen moves, which
is set with the SC command. Rather, it is an intentional delay of a given
duration, to force the EBB not to execute the next command (often an SM) for
some length of time, which allows the pen move to complete and possibly some
extra settling time before moving the other motors.

If no duration argument is specified, a value of 0 milliseconds is used
internally.
*/
void EBBParser::parseTP(const char* arg)
{
    sendAck();

    const short delayMs = (arg != NULL) ? atoi(arg) : 0;

    setPenState(!getPenState(), delayMs);
}
Beispiel #15
0
void EBBParser::parseStream()
{
    if (!mStream.available())
        return;

    const char inChar = mStream.read();
    if (inChar != '\r') {
        if (mReadBuffer.length() < 64 && isprint(inChar))
            mReadBuffer += inChar;
        return;
    }

    char* str = mReadBuffer.begin();
    const char* cmd = strsep(&str, ",");
    const char* arg1 = strsep(&str, ",");
    const char* arg2 = strsep(&str, ",");
    const char* arg3 = strsep(&str, ",");

    if (strcmp(cmd, "EM") == 0) {
        parseEM(arg1, arg2);
    } else if (strcmp(cmd, "ND") == 0) {
        parseND();
    } else if (strcmp(cmd, "NI") == 0) {
        parseNI();
    } else if (strcmp(cmd, "PD") == 0) {
        sendAck();
    } else if (strcmp(cmd, "PO") == 0) {
        parsePO(arg1, arg2, arg3);
    } else if (strcmp(cmd, "QB") == 0) {
        parseQB();
    } else if (strcmp(cmd, "QL") == 0) {
        parseQL();
    } else if (strcmp(cmd, "QN") == 0) {
        parseQN();
    } else if (strcmp(cmd, "QP") == 0) {
        parseQP();
    } else if (strcmp(cmd, "SC") == 0) {
        parseSC(arg1, arg2);
    } else if (strcmp(cmd, "SE") == 0) {
        parseSE(arg1, arg2, arg3);
    } else if (strcmp(cmd, "SL") == 0) {
        parseSL(arg1);
    } else if (strcmp(cmd, "SM") == 0) {
        parseSM(arg1, arg2, arg3);
    } else if (strcmp(cmd, "SN") == 0) {
        parseSN(arg1);
    } else if (strcmp(cmd, "SP") == 0) {
        parseSP(arg1, arg2, arg3);
    } else if (strcmp(cmd, "TP") == 0) {
        parseTP(arg1);
    } else if (strcmp(cmd, "v") == 0) {
        parseV();
    } else
        sendError();

    mReadBuffer = "";
}
/* timeoutHandler - This function is called on the 500msec timeout and individual/cumulative ack is sent to the server depending on the number of packets that have been received  */
void timeoutHandler(void) {

  sendAck(ackSeqNumber, receiveWindowFree);
  it_val.it_interval.tv_sec = 0;
  it_val.it_interval.tv_usec = 0;
  it_val.it_value.tv_sec = 0;
  it_val.it_value.tv_usec = 0;
  setitimer(ITIMER_REAL, &it_val, 0);
}
Beispiel #17
0
	/// <summary>
	/// Receive the specified buffer.
	/// </summary>
	/// <param name='buffer'>
	/// Buffer.
	/// </param>
	short Transport::receive(char buf[], short size)
	{
		short bytesRead;
		bytesRead = link->receive(this->buffer,size+ACKSIZE);

		while(!checksum->checkChecksum(this->buffer,bytesRead))
		{
			sendAck(false);
			bytesRead = link->receive(this->buffer,size+ACKSIZE);
			std::cout<<"Error in checksum\r\n";
		}

		sendAck(true);
		std::cout<<"Checksum Ok\r\n";
		memcpy(buf,buffer+ACKSIZE,bytesRead-ACKSIZE);
		return bytesRead-ACKSIZE;
		
	}
Beispiel #18
0
/**
"SL" — Set Layer

Command: SL,NewLayerValue<CR>
Response: OK<NL><CR>
Firmware versions: v1.9.2 and newer
Execution: Immediate
Arguments:
NewLayerValue is an integer between 0 and 127.
Description:
This command sets the value of the Layer variable, which can be read by the QL
query. This variable is a single unsigned byte, and is available for the user to
store a single variable as needed.

Example: SL,4\r Set the Layer variable to 4.
Example: SL,125\r Set the Layer variable to 125.
Version History: Added in v1.9.2
*/
void EBBParser::parseSL(const char* arg)
{
    if (arg == NULL) {
        sendError();
        return;
    }
    sendAck();

    mLayer = atoi(arg);
}
Beispiel #19
0
/**
"SN" — Set node count

Command: SN,value<CR>
Response: OK<NL><CR>
Firmware versions: v1.9.5 and newer
Execution: Immediate
Arguments:
value is an unsigned long (four byte) integer.
Description:
This command sets the Node Counter to value.

See the "QN" command for a description of the node counter and its operations.

Example: SN,123456789\r Set node counter to 123456789.
Version History: Added in v1.9.5
*/
void EBBParser::parseSN(const char* arg)
{
    if (arg == NULL) {
        sendError();
        return;
    }
    sendAck();

    mNodeCount = atoi(arg);
}
Beispiel #20
0
/**
"PO" — Pin Output

Command: PO,Port,Pin,Value<CR>
Response: OK<NL><CR>
Firmware versions: All
Execution: Immediate
Arguments:
Port: is one of the following letters: A,B,C,D,E. It specifies which port on the
processor is to be used for the output.
Pin: is an integer in the range from 0 through 7. It specifies the pin to be
used for the output.
Value: is either 0 or 1. It specifies the logical value to be output on the pin.
Description:
This command outputs a digital value of a 0 (0V) or 1 (3.3V) on one of the pins
on the processor, as specified by Port and Pin.

This command will not change a pin's direction to output first, so you must set
the pin's direction to be an output using the PD command first if you want
anything to come out of the pin.

This command is a very low-level I/O command. Many other higher level commands
(like SM, S2, etc.) will over-write the output state of pins that they need.
This commands allows you low-level access to every pin on the processor.

Example: PO,C,7,1\r This command would set the pin RC7 (or Port C, pin 7) to a
high value.
*/
void EBBParser::parsePO(const char* arg1, const char* arg2, const char* arg3)
{
    if (arg1 == NULL || arg2 == NULL || arg3 == NULL) {
        sendError();
        return;
    }
    sendAck();

    setPinOutput(arg1[0], atoi(arg2), atoi(arg3));
}
void onCommandZeroEncoderAngle()
{
	if (isReadCommand(gParameters[1]))
	{
		zeroEncoderAngle();
		sendAck();
	}
	else
	{
		sendReadOnlyError();
	}
}
void onCommandEcho()
{
	if (gParameters[0] != NULL)
	{
		Serial.println(gParameters[0]);
		sendAck();
	}
	else
	{
		sendNack();
	}
}
void onCommandVersion()
{
	if (isReadCommand(gParameters[0]))
	{
		sendDouble(FIRMWARE_VERSION);
		sendAck();
	}
	else
	{
		sendReadOnlyError();
	}
}
void onCommandChangelog()
{
	if (isReadCommand(gParameters[0]))
	{
		Serial.println(F("Added PING command"));
		sendAck();
	}
	else
	{
		sendReadOnlyError();
	}
}
void ServiceServerThread::parseData(const QString &dataReceived)
{
    QStringList splitData = dataReceived.split(" ");

    if(splitData.size() > 1) {
        QString numberOfChars = splitData.at(0);

        bool ok;
        int messageLength = numberOfChars.toInt(&ok);
        if(ok) {
            QString message = dataReceived.mid(numberOfChars.size()+1,messageLength);
            if( message == MSG_UIFORCAR ) {
                sendAck();
                emit forcarColeta();
            } else if( message == MSG_UIFINALIZAR ) {
                sendAck();
                emit finalizarCacic();
            }
        }
    }
}
void onCommandSafety()
{
	if (isReadCommand(gParameters[0]))
	{
		sendOnOffStatus(isSafetyOn);
		sendAck();
	}
	else if (isOnCommandArg(gParameters[0]))
	{
		isSafetyOn = true;
		sendAck();
	}
	else if (isOffCommandArg(gParameters[0]))
	{
		isSafetyOn = false;
		sendAck();
	}
	else
	{
		sendOnOffError();
	}
}
void onCommandVerbose()
{
	if (isReadCommand(gParameters[0]))
	{
		sendOnOffStatus(isVerboseMode);
		sendAck();
	}
	else if (isOnCommandArg(gParameters[0]))
	{
		isVerboseMode = true;
		sendAck();
	}
	else if (isOffCommandArg(gParameters[0]))
	{
		isVerboseMode = false;
		sendAck();
	}
	else
	{
		sendOnOffError();
	}
}
Beispiel #28
0
/**
"SE" — Set Engraver

Command: SE,state[,power[,use_motion_queue]]<CR>
Response: OK<NL><CR>
Firmware versions: v2.1.0 and newer (with changes)
Execution: Added to FIFO motion queue
Arguments:
state may be either 0 to disable or 1 to enable the engraver output.
power is an optional argument, with allowed values of integers in the range 0 to
1023.
use_motion_queue is an optional argument, with allowed values of 0 (immediate)
or 1 (use motion queue).
Description:
This command is used to enable and disable the engraver PWM output on RB3
(called B3 on the board), and also set its output power. Use SE,0 to disable
this feature.

The power argument represents the power (duty cycle of the PWM signal), where 0
is always off and 1023 is always on. If this optional argument is not included,
then the power will be set at 512 (50%) duty cycle.

If the use_motion_queue parameter has the value of 1, then this SE command will
be added to the motion queue just like SM and SP commands, and thus will be
executed when the previous motion commands have finished. Note that if you need
to use this argument, the power argument is not optional. If use_motion_queue
has value 0 (or if it is omitted) the command is executed immediately, and is
not added to the queue.

Example: SE,1,1023\r Turns on the engraver output with maximum power
Example: SE,0\r Turns off the engraver output
Example: SE,0,0,1\r Adds a command to the motion queue, that (when executed)
turns off the engraver output.
*/
void EBBParser::parseSE(const char* arg1, const char* arg2, const char* arg3)
{
    if (arg1 == NULL) {
        sendError();
        return;
    }
    sendAck();

    const bool state = atoi(arg1);
    const int power = (arg2 != NULL) ? atoi(arg2) : 512;

    setEngraverState(state, power);
}
Beispiel #29
0
void CDStarControl::clock(unsigned int ms)
{
	if (m_network != NULL)
		writeNetwork();

	m_ackTimer.clock(ms);
	if (m_ackTimer.isRunning() && m_ackTimer.hasExpired()) {
		sendAck();
		m_ackTimer.stop();
	}

	m_holdoffTimer.clock(ms);
	if (m_holdoffTimer.isRunning() && m_holdoffTimer.hasExpired())
		m_holdoffTimer.stop();

	m_timeoutTimer.clock(ms);

	if (m_state == RS_RELAYING_NETWORK_AUDIO) {
		m_networkWatchdog.clock(ms);

		if (m_networkWatchdog.hasExpired()) {
			// We're received the header haven't we?
			m_frames += 1U;
			if (m_bits == 0U) m_bits = 1U;
			LogMessage("D-Star, network watchdog has expired, %.1f seconds,  %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));
			m_timeoutTimer.stop();
			writeEndOfTransmission();
#if defined(DUMP_DSTAR)
			closeFile();
#endif
		}
	}

	if (m_state == RS_RELAYING_NETWORK_AUDIO) {
		m_packetTimer.clock(ms);

		if (m_packetTimer.isRunning() && m_packetTimer.hasExpired()) {
			unsigned int frames = m_elapsed.elapsed() / DSTAR_FRAME_TIME;

			if (frames > m_frames) {
				unsigned int count = frames - m_frames;
				if (count > 3U) {
					LogMessage("D-Star, lost audio for 300ms filling in, %u %u", frames, m_frames);
					insertSilence(count - 1U);
				}
			}

			m_packetTimer.start();
		}
	}
}
void onCommandDacVoltage()
{
	if (isChannelCorrect(gParameters[0]))
	{
		uint8_t channel = convertToInt(gParameters[0]);
		double voltage = atof(gParameters[1]);

		if (isReadCommand(gParameters[1]))
		{
			sendDouble(currentVoltages[channel]);
			sendAck();
		}
		else
		{
			if (!isSafetyOn)
			{
				if (isDoubleWithinRange(voltage, MOTOR_MIN_VOLTAGE, MOTOR_MAX_VOLTAGE))
				{
					setDacVoltage(channel, voltage);
					sendAck();
				}
				else
				{
					sendDoubleRangeError(MOTOR_MIN_VOLTAGE, MOTOR_MAX_VOLTAGE, VOLTAGE_UNIT);
				}
			}
			else
			{
				Serial.println(F("Cannot change voltage while safety is on."));
				sendNack();
			}
		}
	}
	else
	{
		sendChannelError();
	}
}