Exemple #1
0
/**
 *	@brief	Enable or disable the rumble.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param status	1 to enable, 0 to disable.
 */
void wiiuse_rumble(struct wiimote_t* wm, int status) {
	byte buf;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return;
	}

	/* make sure to keep the current lit leds */
	buf = wm->leds;

	if (status) {
		WIIUSE_DEBUG("Starting rumble...");
		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
		buf |= 0x01;
	} else {
		WIIUSE_DEBUG("Stopping rumble...");
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
		buf &= ~(0x01);
	}

	/* preserve IR state */
	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
		buf |= 0x04;
	}

	wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
}
Exemple #2
0
void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) {
	/* send request to wiimote for accelerometer calibration */
	byte buf[MAX_PAYLOAD];

	/* step 0 - Reset wiimote */
	{
		//wiiuse_set_leds(wm, WIIMOTE_LED_NONE);

		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
		WIIMOTE_DISABLE_FLAG(wm, WIIUSE_CONTINUOUS);

		wiiuse_set_report_type(wm);
		wiiuse_millisleep(500);

		WIIUSE_DEBUG("Wiimote reset!\n");
	}

	/* step 1 - calibration of accelerometers */
	if(wm->type != WIIUSE_WIIMOTE_MOTION_PLUS_INSIDE)
	{
		struct accel_t* accel = &wm->accel_calib;

		wiiuse_read_data_sync(wm, 1, WM_MEM_OFFSET_CALIBRATION, 8, buf);

		/* received read data */
		accel->cal_zero.x = buf[0];
		accel->cal_zero.y = buf[1];
		accel->cal_zero.z = buf[2];

		accel->cal_g.x = buf[4] - accel->cal_zero.x;
		accel->cal_g.y = buf[5] - accel->cal_zero.y;
		accel->cal_g.z = buf[6] - accel->cal_zero.z;

		WIIUSE_DEBUG("Calibrated wiimote acc\n");
	}

	/* step 2 - re-enable IR and ask for status */
	{
		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);

		/* now enable IR if it was set before the handshake completed */
		if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
			WIIUSE_DEBUG("Handshake finished, enabling IR.");
			WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
			wiiuse_set_ir(wm, 1);
		}

		WIIUSE_DEBUG("Asking for status ...\n");
		wm->event = WIIUSE_CONNECT;
		wiiuse_status(wm);
	}
}
Exemple #3
0
/**
 *	@brief Handle the handshake data from the wiiboard.
 *
 *	@param wb		A pointer to a wii_board_t structure.
 *	@param data		The data read in from the device.
 *	@param len		The length of the data block, in bytes.
 *
 *	@return	Returns 1 if handshake was successful, 0 if not.
 */
int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, ubyte* data, uword len) 
{
	int offset = 0;

	if (data[offset]==0xff) {
		if (data[offset+16]==0xff) {
			WIIUSE_DEBUG("Wii Balance Board handshake appears invalid, trying again.");
			wiiuse_read_data(wm, data, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN, wiiuse_handshake_expansion);
			return 0;
		}
		offset += 16;
	}

	wb->ctr[0] = (data[offset+4]<<8)|data[offset+5];
	wb->cbr[0] = (data[offset+6]<<8)|data[offset+7];
	wb->ctl[0] = (data[offset+8]<<8)|data[offset+9];
	wb->cbl[0] = (data[offset+10]<<8)|data[offset+11];

	wb->ctr[1] = (data[offset+12]<<8)|data[offset+13];
	wb->cbr[1] = (data[offset+14]<<8)|data[offset+15];
	wb->ctl[1] = (data[offset+16]<<8)|data[offset+17];
	wb->cbl[1] = (data[offset+18]<<8)|data[offset+19];

	wb->ctr[2] = (data[offset+20]<<8)|data[offset+21];
	wb->cbr[2] = (data[offset+22]<<8)|data[offset+23];
	wb->ctl[2] = (data[offset+24]<<8)|data[offset+25];
	wb->cbl[2] = (data[offset+26]<<8)|data[offset+27];

	/* handshake done */
	wm->event = WIIUSE_WII_BOARD_INSERTED;
	wm->exp.type = EXP_WII_BOARD;

	return 1;
}
Exemple #4
0
/**
 *	@brief Send the next pending data read request to the wiimote.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *
 *	@see wiiuse_read_data()
 *
 *	This function is not part of the wiiuse API.
 */
void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
	byte buf[6];
	struct read_req_t* req;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return;
	}
	if (!wm->read_req)	{
		return;
	}

	/* skip over dirty ones since they have already been read */
	req = wm->read_req;
	while (req && req->dirty) {
		req = req->next;
	}
	if (!req) {
		return;
	}

	/* the offset is in big endian */
	to_big_endian_uint32_t(buf, req->addr);

	/* the length is in big endian */
	to_big_endian_uint16_t(buf + 4, req->size);

	WIIUSE_DEBUG("Request read at address: 0x%x  length: %i", req->addr, req->size);
	wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6);
}
Exemple #5
0
int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb)
{
	ubyte buf[2];
	int motion,ir,exp;

	if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;

	buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00);	/* set to 0x04 for continuous reporting */
	buf[1] = 0x00;

	motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
	exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
	ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);

	if (motion && ir && exp)	buf[1] = WM_RPT_BTN_ACC_IR_EXP;
	else if (motion && exp)		buf[1] = WM_RPT_BTN_ACC_EXP;
	else if (motion && ir)		buf[1] = WM_RPT_BTN_ACC_IR;
	else if (ir && exp)			buf[1] = WM_RPT_BTN_IR_EXP;
	else if (ir)				buf[1] = WM_RPT_BTN_ACC_IR;
	else if (exp)				buf[1] = WM_RPT_BTN_EXP;
	else if (motion)			buf[1] = WM_RPT_BTN_ACC;
	else						buf[1] = WM_RPT_BTN;

	WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);

	wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb);
	return buf[1];
}
Exemple #6
0
/**
 *	@brief	Read data from the wiimote (callback version).
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param read_cb	Function pointer to call when the data arrives from the wiimote.
 *	@param buffer	An allocated buffer to store the data as it arrives from the wiimote.
 *					Must be persistent in memory and large enough to hold the data.
 *	@param addr		The address of wiimote memory to read from.
 *	@param len		The length of the block to be read.
 *
 *	The library can only handle one data read request at a time
 *	because it must keep track of the buffer and other
 *	events that are specific to that request.  So if a request
 *	has already been made, subsequent requests will be added
 *	to a pending list and be sent out when the previous
 *	finishes.
 */
int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, uint16_t len) {
	struct read_req_t* req;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return 0;
	}
	if (!buffer || !len) {
		return 0;
	}

	/* make this request structure */
	req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
	if (req == NULL) {
		return 0;
	}
	req->cb = read_cb;
	req->buf = buffer;
	req->addr = addr;
	req->size = len;
	req->wait = len;
	req->dirty = 0;
	req->next = NULL;

	/* add this to the request list */
	if (!wm->read_req) {
		/* root node */
		wm->read_req = req;

		WIIUSE_DEBUG("Data read request can be sent out immediately.");

		/* send the request out immediately */
		wiiuse_send_next_pending_read_request(wm);
	} else {
		struct read_req_t* nptr = wm->read_req;
		for (; nptr->next; nptr = nptr->next) {
			;
		}
		nptr->next = req;

		WIIUSE_DEBUG("Added pending data read request.");
	}

	return 1;
}
Exemple #7
0
/**
 *	@brief Request the wiimote controller status.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *
 *	Controller status includes: battery level, LED status, expansions
 */
void wiiuse_status(struct wiimote_t* wm) {
	byte buf = 0;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return;
	}

	WIIUSE_DEBUG("Requested wiimote status.");

	wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
}
Exemple #8
0
/**
 *	@brief	Set the report type based on the current wiimote state.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *
 *	@return The report type sent.
 *
 *	The wiimote reports formatted packets depending on the
 *	report type that was last requested.  This function will
 *	update the type of report that should be sent based on
 *	the current state of the device.
 */
int wiiuse_set_report_type(struct wiimote_t* wm) {

    byte buf[2];
	int motion, exp, ir, balance_board;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return 0;
	}

	buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00);	/* set to 0x04 for continuous reporting */
	buf[1] = 0x00;

	/* if rumble is enabled, make sure we keep it */
	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) {
		buf[0] |= 0x01;
	}

	motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
	exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
	ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
	balance_board = exp && (wm->exp.type == EXP_WII_BOARD);

	if (motion && ir && exp)	{
		buf[1] = WM_RPT_BTN_ACC_IR_EXP;
	} else if (motion && exp) {
		buf[1] = WM_RPT_BTN_ACC_EXP;
	} else if (motion && ir) {
		buf[1] = WM_RPT_BTN_ACC_IR;
	} else if (ir && exp) {
		buf[1] = WM_RPT_BTN_IR_EXP;
	} else if (ir) {
		buf[1] = WM_RPT_BTN_ACC_IR;
	} else if(exp && balance_board) {
        if(wm->exp.wb.use_alternate_report)
	        buf[1] = WM_RPT_BTN_EXP_8;
        else
            buf[1] = WM_RPT_BTN_EXP;
	} else if (exp) {
		buf[1] = WM_RPT_BTN_EXP;
	} else if (motion) {
		buf[1] = WM_RPT_BTN_ACC;
	} else {
		buf[1] = WM_RPT_BTN;
	}

	WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);

	exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
	if (exp <= 0) {
		return exp;
	}

	return buf[1];
}
Exemple #9
0
/**
*    @brief Wait until specified report arrives and return it
*
*    @param wm             Pointer to a wiimote_t structure.
*    @param buffer         Pre-allocated memory to store the received data
*    @param bufferLength   size of buffer in bytes
*
*    Synchronous/blocking, this function will not return until it receives the specified
*    report from the Wiimote.
*
*/
void wiiuse_wait_report(struct wiimote_t *wm, int report, byte *buffer, int bufferLength) {
	for (;;) {
		if (wiiuse_os_read(wm, buffer, bufferLength) > 0) {
			if (buffer[0] == report) {
				break;
			} else {
				WIIUSE_DEBUG("(id %i) dropping report 0x%x, waiting for 0x%x", wm->unid, buffer[0], report);
			}
		}
	}
}
Exemple #10
0
/**
 *	@brief	Write data to the wiimote (callback version).
 *
 *	@param wm			Pointer to a wiimote_t structure.
 *	@param addr			The address to write to.
 *	@param data			The data to be written to the memory location.
 *	@param len			The length of the block to be written.
 *	@param cb			Function pointer to call when the data arrives from the wiimote.
 *
 *	The library can only handle one data read request at a time
 *	because it must keep track of the buffer and other
 *	events that are specific to that request.  So if a request
 *	has already been made, subsequent requests will be added
 *	to a pending list and be sent out when the previous
 *	finishes.
 */
int wiiuse_write_data_cb(struct wiimote_t *wm, unsigned int addr, byte *data, byte len, wiiuse_write_cb write_cb) {
	struct data_req_t* req;

	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
		return 0;
	}
	if (!data || !len) {
		return 0;
	}

	req = (struct data_req_t*)malloc(sizeof(struct data_req_t));
	req->cb = write_cb;
	req->len = len;
	memcpy(req->data, data, req->len);
	req->state = REQ_READY;
	req->addr = addr;/* BIG_ENDIAN_LONG(addr); */
	req->next = NULL;
	/* add this to the request list */
	if (!wm->data_req) {
		/* root node */
		wm->data_req = req;

		WIIUSE_DEBUG("Data write request can be sent out immediately.");

		/* send the request out immediately */
		wiiuse_send_next_pending_write_request(wm);
	} else {
		struct data_req_t* nptr = wm->data_req;
		WIIUSE_DEBUG("chaud2fois");
		for (; nptr->next; nptr = nptr->next) {
			;
		}
		nptr->next = req;

		WIIUSE_DEBUG("Added pending data write request.");
	}

	return 1;
}
Exemple #11
0
/**
 *	@brief	Set the IR sensitivity.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param level	1-5, same as Wii system sensitivity setting.
 *
 *	If the level is < 1, then level will be set to 1.
 *	If the level is > 5, then level will be set to 5.
 */
void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
	char* block1 = NULL;
	char* block2 = NULL;

	if (!wm)	return;

	if (level > 5)		level = 5;
	if (level < 1)		level = 1;

	WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
								WIIMOTE_STATE_IR_SENS_LVL2 |
								WIIMOTE_STATE_IR_SENS_LVL3 |
								WIIMOTE_STATE_IR_SENS_LVL4 |
								WIIMOTE_STATE_IR_SENS_LVL5));

	switch (level) {
		case 1:
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
			break;
		case 2:
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
			break;
		case 3:
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
			break;
		case 4:
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
			break;
		case 5:
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
			break;
		default:
			return;
	}

	/* set the new sensitivity */
	get_ir_sens(wm, &block1, &block2);

	wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
	wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);

	WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
}
Exemple #12
0
/**
 *	@brief	Write data to the wiimote.
 *
 *	@param wm			Pointer to a wiimote_t structure.
 *	@param addr			The address to write to.
 *	@param data			The data to be written to the memory location.
 *	@param len			The length of the block to be written.
 */
int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, const byte* data, byte len) {
	byte buf[21] = {0};		/* the payload is always 23 */

	byte * bufPtr = buf;
	if (!wm || !WIIMOTE_IS_CONNECTED(wm)) {
            WIIUSE_ERROR("Attempt to write, but no wiimote available or not connected!");
            return 0;
	}
	if (!data || !len) {
            WIIUSE_ERROR("Attempt to write, but no data or length == 0");
            return 0;
	}

	WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr);

#ifdef WITH_WIIUSE_DEBUG
	{
		int i = 0;
		printf("Write data is: ");
		for (; i < len; ++i) {
			printf("%x ", data[i]);
		}
		printf("\n");
	}
#endif

	/* the offset is in big endian */
	buffer_big_endian_uint32_t(&bufPtr, (uint32_t)addr);

	/* length */
	buffer_big_endian_uint8_t(&bufPtr, len);

	/* data */
	memcpy(bufPtr, data, len);

	wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
	return 1;
}
Exemple #13
0
/**
 *	@brief	Set if the wiimote should track IR targets.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param status	1 to enable, 0 to disable.
 */
void wiiuse_set_ir(struct wiimote_t* wm, int status) {
	byte buf;
	char* block1 = NULL;
	char* block2 = NULL;
	int ir_level;

	if (!wm)
		return;

	/*
	 *	Wait for the handshake to finish first.
	 *	When it handshake finishes and sees that
	 *	IR is enabled, it will call this function
	 *	again to actually enable IR.
	 */
	if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
		if(status) {
			WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.");
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
		} // else ignoring request to turn off, since it's turned off by default
		return;
	}

	/*
	 *	Check to make sure a sensitivity setting is selected.
	 */
	ir_level = get_ir_sens(wm, &block1, &block2);
	if (!ir_level) {
		WIIUSE_ERROR("No IR sensitivity setting selected.");
		return;
	}

	if (status) {
		/* if already enabled then stop */
		if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
			return;
		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
	} else {
		/* if already disabled then stop */
		if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
			return;
		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
	}

	/* set camera 1 and 2 */
	buf = (status ? 0x04 : 0x00);
	wiiuse_send(wm, WM_CMD_IR, &buf, 1);
	wiiuse_send(wm, WM_CMD_IR_2, &buf, 1);

	if (!status) {
		WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
		wiiuse_set_report_type(wm);
		return;
	}

	/* enable IR, set sensitivity */
	buf = 0x08;
	wiiuse_write_data(wm, WM_REG_IR, &buf, 1);

	/* wait for the wiimote to catch up */
	#ifndef WIN32
		usleep(50000);
	#else
		Sleep(50);
	#endif

	/* write sensitivity blocks */
	wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
	wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);

	/* set the IR mode */
	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
		buf = WM_IR_TYPE_BASIC;
	else
		buf = WM_IR_TYPE_EXTENDED;
	wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1);

	#ifndef WIN32
		usleep(50000);
	#else
		Sleep(50);
	#endif

	/* set the wiimote report type */
	wiiuse_set_report_type(wm);

	WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
}
Exemple #14
0
/**
 *	@brief Interpret IR data into more user friendly variables.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 */
static void interpret_ir_data(struct wiimote_t* wm) {
	struct ir_dot_t* dot = wm->ir.dot;
	int i;
	float roll = 0.0f;
	int last_num_dots = wm->ir.num_dots;

	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
		roll = wm->orient.roll;

	/* count visible dots */
	wm->ir.num_dots = 0;
	for (i = 0; i < 4; ++i) {
		if (dot[i].visible)
			wm->ir.num_dots++;
	}

	switch (wm->ir.num_dots) {
		case 0:
		{
			wm->ir.state = 0;

			/* reset the dot ordering */
			for (i = 0; i < 4; ++i)
				dot[i].order = 0;

			wm->ir.x = 0;
			wm->ir.y = 0;
			wm->ir.z = 0.0f;

			return;
		}
		case 1:
		{
			fix_rotated_ir_dots(wm->ir.dot, roll);

			if (wm->ir.state < 2) {
				/*
				 *	Only 1 known dot, so use just that.
				 */
				for (i = 0; i < 4; ++i) {
					if (dot[i].visible) {
						wm->ir.x = dot[i].x;
						wm->ir.y = dot[i].y;

						wm->ir.ax = wm->ir.x;
						wm->ir.ay = wm->ir.y;

						/*	can't calculate yaw because we don't have the distance */
						//wm->orient.yaw = calc_yaw(&wm->ir);

						ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
						break;
					}
				}
			} else {
				/*
				 *	Only see 1 dot but know theres 2.
				 *	Try to estimate where the other one
				 *	should be and use that.
				 */
				for (i = 0; i < 4; ++i) {
					if (dot[i].visible) {
						int ox = 0;
						int x, y;

						if (dot[i].order == 1)
							/* visible is the left dot - estimate where the right is */
							ox = dot[i].x + wm->ir.distance;
						else if (dot[i].order == 2)
							/* visible is the right dot - estimate where the left is */
							ox = dot[i].x - wm->ir.distance;

						x = ((signed int)dot[i].x + ox) / 2;
						y = dot[i].y;

						wm->ir.ax = x;
						wm->ir.ay = y;
						wm->orient.yaw = calc_yaw(&wm->ir);

						if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
							ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
							wm->ir.x = x;
							wm->ir.y = y;
						}

						break;
					}
				}
			}

			break;
		}
		case 2:
		case 3:
		case 4:
		{
			/*
			 *	Two (or more) dots known and seen.
			 *	Average them together to estimate the true location.
			 */
			int x, y;
			wm->ir.state = 2;

			fix_rotated_ir_dots(wm->ir.dot, roll);

			/* if there is at least 1 new dot, reorder them all */
			if (wm->ir.num_dots > last_num_dots) {
				reorder_ir_dots(dot);
				wm->ir.x = 0;
				wm->ir.y = 0;
			}

			wm->ir.distance = ir_distance(dot);
			wm->ir.z = 1023 - wm->ir.distance;

			get_ir_dot_avg(wm->ir.dot, &x, &y);

			wm->ir.ax = x;
			wm->ir.ay = y;
			wm->orient.yaw = calc_yaw(&wm->ir);

			if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
				ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
				wm->ir.x = x;
				wm->ir.y = y;
			}

			break;
		}
		default:
		{
			break;
		}
	}

	#ifdef WITH_WIIUSE_DEBUG
	{
	int ir_level;
	WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level);
	WIIUSE_DEBUG("IR sensitivity: %i", ir_level);
	WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots);
	for (i = 0; i < 4; ++i)
		if (dot[i].visible)
			WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
	WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
	}
	#endif
}
Exemple #15
0
void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) {
	if (!wm)	{
		return;
	}

	switch (wm->handshake_state) {
		case 0: {
				byte* buf;

				/* continuous reporting off, report to buttons only */
				WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
				wiiuse_set_leds(wm, WIIMOTE_LED_NONE);

				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
				WIIMOTE_DISABLE_FLAG(wm, WIIUSE_CONTINUOUS);

				wiiuse_set_report_type(wm);

				/* send request to wiimote for accelerometer calibration */
				buf = (byte*)malloc(sizeof(byte) * 8);
				wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7);
				wm->handshake_state++;

				wiiuse_set_leds(wm, WIIMOTE_LED_NONE);

				break;
			}

		case 1: {
				struct read_req_t* req = wm->read_req;
				struct accel_t* accel = &wm->accel_calib;
				byte val;

				/* received read data */
				accel->cal_zero.x = req->buf[0];
				accel->cal_zero.y = req->buf[1];
				accel->cal_zero.z = req->buf[2];

				accel->cal_g.x = req->buf[4] - accel->cal_zero.x;
				accel->cal_g.y = req->buf[5] - accel->cal_zero.y;
				accel->cal_g.z = req->buf[6] - accel->cal_zero.z;

				/* done with the buffer */
				free(req->buf);

				/* handshake is done */
				WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x",
				             accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z,
				             accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);

				/* M+ off */
				val = 0x55;
				wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &val, 1, wiiuse_disable_motion_plus1);

				break;
			}

		case 2: {
				/* request the status of the wiimote to check for any expansion */
				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
				WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
				wm->handshake_state++;

				/* now enable IR if it was set before the handshake completed */
				if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
					WIIUSE_DEBUG("Handshake finished, enabling IR.");
					WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
					wiiuse_set_ir(wm, 1);
				}

				wm->event = WIIUSE_CONNECT;
				wiiuse_status(wm);

				break;
			}

		default: {
				break;
			}
	}
}
Exemple #16
0
/**
 *	@brief Handle the handshake data from the nunchuk.
 *
 *	@param nc		A pointer to a nunchuk_t structure.
 *	@param data		The data read in from the device.
 *	@param len		The length of the data block, in bytes.
 *
 *	@return	Returns 1 if handshake was successful, 0 if not.
 */
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) {
	int i;
	int offset = 0;

	nc->btns = 0;
	nc->btns_held = 0;
	nc->btns_released = 0;

	/* set the smoothing to the same as the wiimote */
	nc->flags = &wm->flags;
	nc->accel_calib.st_alpha = wm->accel_calib.st_alpha;

	/* decrypt data */
	for (i = 0; i < len; ++i)
		data[i] = (data[i] ^ 0x17) + 0x17;

	if (data[offset] == 0xFF) {
		/*
		 *	Sometimes the data returned here is not correct.
		 *	This might happen because the wiimote is lagging
		 *	behind our initialization sequence.
		 *	To fix this just request the handshake again.
		 *
		 *	Other times it's just the first 16 bytes are 0xFF,
		 *	but since the next 16 bytes are the same, just use
		 *	those.
		 */
		if (data[offset + 16] == 0xFF) {
			/* get the calibration data */
			byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));

			WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
			wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);

			return 0;
		} else
			offset += 16;
	}

	nc->accel_calib.cal_zero.x = data[offset + 0];
	nc->accel_calib.cal_zero.y = data[offset + 1];
	nc->accel_calib.cal_zero.z = data[offset + 2];
	nc->accel_calib.cal_g.x = data[offset + 4];
	nc->accel_calib.cal_g.y = data[offset + 5];
	nc->accel_calib.cal_g.z = data[offset + 6];
	nc->js.max.x = data[offset + 8];
	nc->js.min.x = data[offset + 9];
	nc->js.center.x = data[offset + 10];
	nc->js.max.y = data[offset + 11];
	nc->js.min.y = data[offset + 12];
	nc->js.center.y = data[offset + 13];

	/* default the thresholds to the same as the wiimote */
	nc->orient_threshold = wm->orient_threshold;
	nc->accel_threshold = wm->accel_threshold;

	/* handshake done */
	wm->exp.type = EXP_NUNCHUK;

	#ifdef WIN32
	wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
	#endif

	return 1;
}
Exemple #17
0
void motion_plus_disconnected(struct motion_plus_t* mp)
{
	WIIUSE_DEBUG("Motion plus disconnected");
	memset(mp, 0, sizeof(struct motion_plus_t));
}
Exemple #18
0
 /**
 *	@brief Get initialization data from the wiimote.
 *
 *	@param wm		Pointer to a wiimote_t structure.
 *	@param data		unused
 *	@param len		unused
 *
 *	When first called for a wiimote_t structure, a request
 *	is sent to the wiimote for initialization information.
 *	This includes factory set accelerometer data.
 *	The handshake will be concluded when the wiimote responds
 *	with this data.
 */
void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) {
	if (!wm)	return;

	switch (wm->handshake_state) {
		case 0:
		{
			/* send request to wiimote for accelerometer calibration */
			byte* buf;

			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
			wiiuse_set_leds(wm, WIIMOTE_LED_NONE);

			buf = (byte*)malloc(sizeof(byte) * 8);
			wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7);
			wm->handshake_state++;

			wiiuse_set_leds(wm, WIIMOTE_LED_NONE);

			break;
		}
		case 1:
		{
			struct read_req_t* req = wm->read_req;
			struct accel_t* accel = &wm->accel_calib;

			/* received read data */
			accel->cal_zero.x = req->buf[0];
			accel->cal_zero.y = req->buf[1];
			accel->cal_zero.z = req->buf[2];

			accel->cal_g.x = req->buf[4] - accel->cal_zero.x;
			accel->cal_g.y = req->buf[5] - accel->cal_zero.y;
			accel->cal_g.z = req->buf[6] - accel->cal_zero.z;

			/* done with the buffer */
			free(req->buf);

			/* handshake is done */
			WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x",
					accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z,
					accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);


			/* request the status of the wiimote to see if there is an expansion */
			wiiuse_status(wm);

			WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
			wm->handshake_state++;

			/* now enable IR if it was set before the handshake completed */
			if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
				WIIUSE_DEBUG("Handshake finished, enabling IR.");
				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
				wiiuse_set_ir(wm, 1);
			}

			break;
		}
		default:
		{
			break;
		}
	}
}