/* Drive the robot with a fixed linear speed, and turning through a fixed radius.
  Do not call this function for the special cases of driving straight, or clockwise
  and counter-clockwise turning; this function instructs the robot to drive only nonzero radii.  */
extern int32_t irobotDriveRadius(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	int16_t					velocity,	/* (in)		Velocity, in mm/s */
	int16_t					radius		/* (in)		Radius, in mm */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_DRIVE_SIZE];

	velocity = coerce(ACTUATOR_WHEEL_SPEED_MIN, velocity, ACTUATOR_WHEEL_SPEED_MAX);
	radius = coerce(ACTUATOR_DRIVE_RADIUS_MIN, radius, ACTUATOR_DRIVE_RADIUS_MAX);

	/* Special case: radius = 1mm is interpreted as CCW rotation;
		iRobot Drive CCW covers this case, so a drive radius of 1mm is
		interpreted as the next smallest radius, 2mm */
	if(radius == 1){
		radius = 2;
	}

	packet[0] = OP_DRIVE;
	packet[1] = HO(velocity);
	packet[2] = LO(velocity);
	packet[3] = HO(radius);
	packet[4] = LO(radius);
	
	return irobotUARTWriteRaw(port, packet, OP_DRIVE_SIZE);
}
int32_t irobotSensorPollSensorGroup6(
	const irobotUARTPort_t	port,
	irobotSensorGroup6_t *	const sensorGroup6
){
	int32_t status = ERROR_SUCCESS;

	// initialize communications buffer
	uint8_t txBuffer[OP_SENSORS_SIZE];
	uint8_t rxQueueBuffer[SENSOR_SIZE_UPPER_BOUND] = {0x00};
	xqueue_t rxQueue;
	xqueue_init(&rxQueue, rxQueueBuffer, SENSOR_SIZE_UPPER_BOUND);

	// check for NULL pointer
	if(!sensorGroup6){
		return ERROR_INVALID_PARAMETER;
	}

	// request packet
	txBuffer[0] = OP_SENSORS;
	txBuffer[1] = SENSOR_GROUP6;
	irobot_StatusMerge(&status, irobotUARTWriteRaw(port, txBuffer, OP_SENSORS_SIZE));
	
	// receive response
	if(!irobot_IsError(status)){
		irobot_StatusMerge(&status, irobotUARTRead(port, &rxQueue, SENSOR_GROUP6_SIZE));
	}

	// read response
	if(!irobot_IsError(status)){
		irobot_StatusMerge(&status, irobotReadSensorGroup6(&rxQueue, sensorGroup6));
	}

	return status;
}
/*	Define a song. Each song is alloted 16 notes, but a song can "spill over" into
	the next if so desired. The maximum number of notes that may be defined is
	(16 - SongNumber) * 16. */
extern int32_t irobotSong(
	const irobotUARTPort_t			port,		/* (in)		UART port */
	uint8_t							songNumber,	/* (in)		Song number */
	const irobotSongNote_t * const	songNotes,	/* (in)		Song notes */
	uint8_t							nNotes		/* (in)		Number of song notes */
){												/* (ret)	Error / success code */
	uint8_t packet[OP_SONG_MAX_LENGTH];
	uint8_t packetIndex = 0;
	uint8_t noteIndex = 0;

	if(!songNotes){
		return ERROR_INVALID_PARAMETER;
	}

	songNumber = fmin(songNumber, ACTUATOR_MAX_SONGS - 1);
	nNotes = fmin(nNotes, (ACTUATOR_MAX_SONGS - songNumber) * ACTUATOR_MAX_NOTES_PER_SONG);

	packet[packetIndex++] = OP_SONG;
	packet[packetIndex++] = songNumber;
	packet[packetIndex++] = nNotes;
	for(noteIndex = 0; noteIndex < nNotes; noteIndex++){
		packet[packetIndex++] = songNotes[noteIndex].midiNote;
		packet[packetIndex++] = songNotes[noteIndex].duration;
	}
	
	return irobotUARTWriteRaw(port, packet, packetIndex);
}
Esempio n. 4
0
/* Change to START mode */
extern int32_t irobotStart(
	const irobotUARTPort_t	port		/* (in)		UART port */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_START_SIZE];

	packet[0] = OP_START;
	
	return irobotUARTWriteRaw(port, packet, OP_START_SIZE);
}
Esempio n. 5
0
/* Stop a running demo */
extern int32_t irobotDemoStop(
	const irobotUARTPort_t	port		/* (in)		UART port */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_DEMO_SIZE];

	packet[0] = OP_DEMO;
	packet[1] = 0xFF;		/* special case; stop all demos */
	
	return irobotUARTWriteRaw(port, packet, OP_DEMO_SIZE);
}
/* Write to the digital output bank of the cargo bay on iRobot. */
extern int32_t irobotDigitalOutputs(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	const uint8_t			output		/* (in)		Pins  0-7 */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_DIGITAL_OUTPUTS_SIZE];
	
	packet[0] = OP_DIGITAL_OUTPUTS;
	packet[1] = output;

	return irobotUARTWriteRaw(port, packet, OP_DIGITAL_OUTPUTS_SIZE);
}
/* Play a song */
extern int32_t irobotPlaySong(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	const uint8_t			songNumber	/* (in)		Song number */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_PLAY_SONG_SIZE];

	packet[0] = OP_PLAY_SONG;
	packet[1] = songNumber;
	
	return irobotUARTWriteRaw(port, packet, OP_PLAY_SONG_SIZE);
}
Esempio n. 8
0
/* pause or resume a sensor stream */
extern int32_t irobotSensorStreamPause(
    const irobotUARTPort_t port,			/* (in)		irobot UART port */
    const bool pause						/* (in)		TRUE if set to pause */
) {
    uint8_t packet[OP_PAUSE_RESUME_STREAM_SIZE];

    packet[0] = OP_PAUSE_RESUME_STREAM;
    packet[1] = !pause;

    return irobotUARTWriteRaw(port, packet, OP_PAUSE_RESUME_STREAM_SIZE);
}
Esempio n. 9
0
/* Run a demo */
extern int32_t irobotDemo(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	const irobotDemo_t		demo		/* (in)		demo to run */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_DEMO_SIZE];

	packet[0] = OP_DEMO;
	packet[1] = (uint8_t)demo;
	
	return irobotUARTWriteRaw(port, packet, OP_DEMO_SIZE);
}
/* Change the state of the iRobot power, play, and advance LEDs. */
extern int32_t irobotLEDs(
	const irobotUARTPort_t	port,			/* (in)		UART port */
	const irobotLED_t		leds,			/* (in)		LEDs to turn on */
	const uint8_t			powerColor,		/* (in)		Power LED color (G[0] - R[255]) */
	const uint8_t			powerIntensity	/* (in)		Power LED intensiy (0-255) */
){											/* (ret)	Error / success code */
	uint8_t packet[OP_LEDS_SIZE];

	packet[0] = OP_LEDS;
	packet[1] = (uint8_t)leds;
	packet[2] = powerColor;
	packet[3] = powerIntensity;
	
	return irobotUARTWriteRaw(port, packet, OP_LEDS_SIZE);
}
/* Drives in a fixed direction  */
extern int32_t irobotDriveDirection(
	const irobotUARTPort_t		port,		/* (in)		UART port */
	int16_t						velocity,	/* (in)		Velocity, in mm/s */
	const irobotDirection_t		direction	/* (in)		direction */
){											/* (ret)	Error / success code */
	uint8_t packet[OP_DRIVE_SIZE];
	
	velocity = coerce(ACTUATOR_WHEEL_SPEED_MIN, velocity, ACTUATOR_WHEEL_SPEED_MAX);

	packet[0] = OP_DRIVE;
	packet[1] = HO(velocity);
	packet[2] = LO(velocity);
	packet[3] = HO((uint16_t)direction);
	packet[4] = LO((uint16_t)direction);

	return irobotUARTWriteRaw(port, packet, OP_DRIVE_SIZE);
}
/* Directly actuate left and right wheels. */
extern int32_t irobotDriveDirect(
	const irobotUARTPort_t	port,			/* (in)		UART port */
	int16_t					leftWheelSpeed,	/* (in)		Left wheels speed, in mm/s */
	int16_t					rightWheelSpeed /* (in)		Right wheel speed, in mm/s */
){											/* (ret)	Error / success code */
	uint8_t packet[OP_DRIVE_DIRECT_SIZE];
	
	leftWheelSpeed = coerce(ACTUATOR_WHEEL_SPEED_MIN, leftWheelSpeed, ACTUATOR_WHEEL_SPEED_MAX);
	rightWheelSpeed = coerce(ACTUATOR_WHEEL_SPEED_MIN, rightWheelSpeed, ACTUATOR_WHEEL_SPEED_MAX);

	packet[0] = OP_DRIVE_DIRECT;
	packet[1] = HO(rightWheelSpeed);
	packet[2] = LO(rightWheelSpeed);
	packet[3] = HO(leftWheelSpeed);
	packet[4] = LO(leftWheelSpeed);

	return irobotUARTWriteRaw(port, packet, OP_DRIVE_DIRECT_SIZE);
}
/* Set the PWM duty cycle of the low-side drivers. */
extern int32_t irobotPWMLowSideDrivers(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	uint8_t					pwm0,		/* (in)		PWM for low-side driver 0 (0-128 duty cycle) */
	uint8_t					pwm1,		/* (in)		PWM for low-side driver 1 (0-128 duty cycle) */
	uint8_t					pwm2		/* (in)		PWM for low-side driver 2 (0-128 duty cycle) */
){										/* (ret)	Error / success code */
	uint8_t packet[OP_PWM_LOW_SIDE_DRIVERS_SIZE];

	pwm0 = coerce(ACTUATOR_PWM_DUTY_MIN, pwm0, ACTUATOR_PWM_DUTY_MAX);
	pwm1 = coerce(ACTUATOR_PWM_DUTY_MIN, pwm1, ACTUATOR_PWM_DUTY_MAX);
	pwm2 = coerce(ACTUATOR_PWM_DUTY_MIN, pwm2, ACTUATOR_PWM_DUTY_MAX);

	packet[0] = OP_PWM_LOW_SIDE_DRIVERS;
	packet[1] = pwm0;
	packet[2] = pwm1;
	packet[3] = pwm2;
	
	return irobotUARTWriteRaw(port, packet, OP_PWM_LOW_SIDE_DRIVERS_SIZE);
}
Esempio n. 14
0
/* configure a sensors stream */
extern int32_t irobotSensorStreamConfigure(
    const irobotUARTPort_t			port,			/* (in)		irobot UART port */
    const irobotSensorCode * const	sensorCodes,	/* (in)		array of sensor codes (must be nSensorCodes in size) */
    const uint8_t					nSensorCodes	/* (in)		number of sensors in each stream packet */
) {													/* (ret)	error / success code */
    uint8_t packet[OP_SENSOR_STREAM_MAX_SIZE];
    uint8_t packetIndex = 0;
    uint8_t sensorCodeIndex = 0;

    /* check for NULL pointers */
    if(nSensorCodes && !sensorCodes) {
        return ERROR_INVALID_PARAMETER;
    }

    packet[packetIndex++] = OP_STREAM;
    packet[packetIndex++] =  fminl(nSensorCodes, OP_SENSOR_STREAM_MAX_CODES);
    for(sensorCodeIndex = 0; sensorCodeIndex < fminl(nSensorCodes, OP_SENSOR_STREAM_MAX_CODES); sensorCodeIndex++) {
        packet[packetIndex++] = sensorCodes[sensorCodeIndex];
    }

    return irobotUARTWriteRaw(port, packet, packetIndex);
}
int32_t irobotUARTWrite(
	const irobotUARTPort_t	port,
	xqueue_t * const		queue
){
	int32_t status = ERROR_SUCCESS;

	// catch NULL pointers
	if(!queue){
		irobot_StatusMerge(&status, ERROR_INVALID_PARAMETER);
	}
	
	// write
	while(!irobot_IsError(status) && !xqueue_empty(queue)){
		uint8_t txByte = xqueue_front(queue);
		irobot_StatusMerge(&status, irobotUARTWriteRaw(port, &txByte, 1));
		if(!irobot_IsError(status)){
			xqueue_drop(queue);
		}
	}

	return status;
}
Esempio n. 16
0
/*	Set the iRobot baud rate; the serial port will be reconfigured to this new
	baud rate and restarted, which will clear communication buffers and may introduce a delay. 

	Note: Baud 115200 appears to be unstable. */
extern int32_t irobotBaudChange(
	const irobotUARTPort_t	port,		/* (in)		UART port */
	const irobotBaud_t		baud		/* (in)		iRobot baud code */
){										/* (ret)	Error / success code */
	int32_t status = ERROR_SUCCESS;
	uint8_t packet[OP_BAUD_SIZE];

	packet[0] = OP_BAUD;
	packet[1] = (uint8_t)baud;
	
	if(!irobot_IsError(status)){
		irobot_StatusMerge(&status, irobotUARTWriteRaw(port, packet, OP_BAUD_SIZE));
	}
	if(!irobot_IsError(status)){
		irobot_StatusMerge(&status, irobotUARTClose(port));
	}
	if(!irobot_IsError(status)){
		irobot_StatusMerge(&status, irobotUARTOpen(port, baud));
		irobotDelayMs(50); /* delay 50ms */
	}

	return status;
}