Exemplo n.º 1
0
// ------------------------------------------------------------------------------------
int _tmain ()
	{
	SetConsoleTitle(_T("- WiiYourself! - Demo: "));
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);

	// write the title
	PrintTitle(console);

	// let's load a couple of samples:
	wiimote_sample sine_sample, daisy_sample;

	// one .raw (just to demonstrate it)
	if(!wiimote::Load16BitMonoSampleRAW(_T("1kSine16 (3130).raw"),
										true, FREQ_3130HZ, sine_sample)) {
		_tprintf(_T("\r  ** can't find 'Sine16 (3130).raw' - (sample won't work!) **"));
		Beep(100, 1000);
		Sleep(3000);
		_tprintf(_T("\r") BLANK_LINE);
		}
	// and one (more convenient) .wav 
	if(!wiimote::Load16bitMonoSampleWAV(_T("Daisy16 (3130).wav"), daisy_sample)) {
		_tprintf(_T("\r  ** can't find 'Daisy16 (3130).wav' - (sample won't work!) **"));
		Beep(100, 1000);
		Sleep(3000);
		_tprintf(_T("\r") BLANK_LINE);
		}

	// create a wiimote object
	wiimote remote;
	
	// in this demo we use a state-change callback to get notified of
	//  extension-related events, and polling for everything else
	// (note you don't have to use both, use whatever suits your app):
	remote.ChangedCallback		= on_state_change;
	//  notify us only when the wiimote connected sucessfully, or something
	//   related to extensions changes
	remote.CallbackTriggerFlags = (state_change_flags)(CONNECTED |
													   EXTENSION_CHANGED |
													   MOTIONPLUS_CHANGED);
reconnect:
	COORD pos = { 0, 6 };
	SetConsoleCursorPosition(console, pos);

	// try to connect the first available wiimote in the system
	//  (available means 'installed, and currently Bluetooth-connected'):
	WHITE; _tprintf(_T("  Looking for a Wiimote     "));
	   
	static const TCHAR* wait_str[] = { _T(".  "), _T(".. "), _T("...") };
	unsigned count = 0;
	while(!remote.Connect(wiimote::FIRST_AVAILABLE)) {
		_tprintf(_T("\b\b\b\b%s "), wait_str[count%3]);
		count++;
#ifdef USE_BEEPS_AND_DELAYS
		Beep(500, 30); Sleep(1000);
#endif
		}

	// connected - light all LEDs
	remote.SetLEDs(0x0f);
	BRIGHT_CYAN; _tprintf(_T("\b\b\b\b... connected!"));
	if(remote.IsBalanceBoard()) {
		BRIGHT_WHITE;_tprintf(_T("  (Balance Board)"));
		}

#ifdef USE_BEEPS_AND_DELAYS
	Beep(1000, 300); Sleep(2000);
#endif

	COORD cursor_pos = { 0, 6 };

#ifdef LOOK_FOR_ADDITIONAL_WIIMOTES
	// try to connect any additional wiimotes (just to show the code)
	_tprintf(_T("\n\n"));

	wiimote  *extra_motes [7] = { NULL }; // 7 should cover it
	unsigned detected		  = 0;
	while(detected < 7)
		{
		wiimote *next = new wiimote;
		if(!next->Connect(wiimote::FIRST_AVAILABLE))
			break;
		extra_motes[detected++] = next;
		
		WHITE		; _tprintf(_T("   also found wiimote "));
		BRIGHT_GREEN; _tprintf(_T("%u"), detected+1);
		if(next->IsBalanceBoard()) {
			WHITE; _tprintf(_T("  (Balance Board)"));
			}
		_tprintf(_T("\n\n"));

# ifdef USE_BEEPS_AND_DELAYS
		Beep(1000 + (detected*100), 100);
		Sleep(500);
# endif
		}
	WHITE; _tprintf( ((detected == 7)? _T("     (can't detect any more).") :
									   _T("    (no more found).")) );
# ifdef USE_BEEPS_AND_DELAYS
	Sleep(2000);
# endif
	// clean up
	for(unsigned index=0; index<detected; index++)
		delete extra_motes[index];
	
	SetConsoleCursorPosition(console, cursor_pos);
#endif // LOOK_FOR_ADDITIONAL_WIIMOTES

	// print the button event instructions:
	BRIGHT_WHITE;
	_tprintf(_T("\r  -- TRY: B = rumble, A = square, 1 = sine, 2 = daisy, Home = Exit --\n"));

	// (stuff for animations)
	DWORD	 last_rumble_time = timeGetTime(); // for rumble text animation
	DWORD    last_led_time    = timeGetTime(); // for led         animation
	bool	 rumble_text	  = true;
	unsigned lit_led          = 0;	
	
	// display the wiimote state data until 'Home' is pressed:
	while(!remote.Button.Home())// && !GetAsyncKeyState(VK_ESCAPE))
		{
		// IMPORTANT: the wiimote state needs to be refreshed each pass
		while(remote.RefreshState() == NO_CHANGE)
			Sleep(1); // // don't hog the CPU if nothing changed

		cursor_pos.Y = 8;
		SetConsoleCursorPosition(console, cursor_pos);

		// did we loose the connection?
		if(remote.ConnectionLost())
			{
			BRIGHT_RED; _tprintf(
				_T("   *** connection lost! ***                                          \n")
				BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE);
			Beep(100, 1000);
			Sleep(2000);
			COORD pos = { 0, 6 };
			SetConsoleCursorPosition(console, pos);
			_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
			goto reconnect;
			}

		// rumble if 'B' (trigger) is pressed
		remote.SetRumble(remote.Button.B());

		// TEMP: Minus button disables MotionPlus (if connected) to allow its
		//        own extension port to work
		static bool last_minus = false;
		if(remote.Button.Minus() && !last_minus && 
		   (remote.ExtensionType == wiimote_state::MOTION_PLUS))
			remote.DisableMotionPlus();
		last_minus = remote.Button.Minus();

		// actions for buttons just pressed/released:
		static bool last_A = false, last_One = false, last_Two = false;

		#define ON_PRESS_RELEASE(button, pressed_action, released_action)	\
			{ bool pressed = remote.Button.button();						\
			  if(pressed)													\
			 	{				   /* just pressed? */						\
				if(!last_##button) pressed_action;							\
				}															\
			else if(last_##button) /* just released */						\
				released_action;											\
			/* remember the current button state for next time */			\
			last_##button = pressed; }
			
		//  play audio whilst certain buttons are held
		if(!remote.IsBalanceBoard()) {
			ON_PRESS_RELEASE(  A, remote.PlaySquareWave(FREQ_3130HZ, 0x20), 
								  remote.EnableSpeaker (false));
			ON_PRESS_RELEASE(One, remote.PlaySample	   (sine_sample),
								  remote.EnableSpeaker (false));
			ON_PRESS_RELEASE(Two, remote.PlaySample	   (daisy_sample),
								  remote.EnableSpeaker (false));
			}

		// Battery level:
		CYAN; _tprintf(_T("  Battery: "));
		// (the green/yellow colour ranges are rough guesses - my wiimote
		//  with rechargeable battery pack fails at around 15%)
		(remote.bBatteryDrained	    )? BRIGHT_RED   :
		(remote.BatteryPercent >= 30)? BRIGHT_GREEN : BRIGHT_YELLOW;
		_tprintf(_T("%3u%%   "), remote.BatteryPercent);

		DWORD current_time = timeGetTime();

		// LEDs:
		//  animate them every second
		if((current_time - last_led_time) >= 1000) {
			remote.SetLEDs((BYTE)(1<<lit_led));
			lit_led		  = (++lit_led) % 4;
			last_led_time = timeGetTime();
			}

		CYAN; _tprintf(_T("LEDs: ")); WHITE; _tprintf(_T("["));
		for(unsigned led=0; led<4; led++)
			{
			if(remote.LED.Lit(led)) {
				BRIGHT_CYAN; _tprintf(_T("*"));
				}
			else{
				WHITE      ; _tprintf(_T("-"));//_T("%c"), '0'+led);
				}
			}

		// Rumble
		WHITE; _tprintf(_T("] "));
		if(remote.bRumble) {
			BRIGHT_WHITE; _tprintf(rumble_text? _T(" RUMBLE") : _T("RUMBLE "));
			// animate the text
			if((current_time - last_rumble_time) >= 110) {
				rumble_text		 = !rumble_text;
				last_rumble_time = current_time;
				}
			}
		else
			_tprintf(_T("       "));

		// Output method:
	    CYAN; _tprintf( _T("        using %s\n"), (remote.IsUsingHIDwrites()?
											   _T("HID writes") : _T("WriteFile()")));
		
		// 'Unique' IDs (not guaranteed to be unique, check the variable
		//  defintion for details)
		CYAN  ; _tprintf(_T("       ID: "));
		YELLOW; _tprintf(_T("%I64u")  , remote.UniqueID);
#ifdef ID2_FROM_DEVICEPATH		// (see comments in header)
		CYAN;  _tprintf(_T("   ID2: "));
		WHITE; _tprintf(_T("%I64u\n"), remote.UniqueID2);
#else
		_tprintf(_T("\n"));
#endif

		// Buttons:
		CYAN; _tprintf(_T("  Buttons: ")); WHITE; _tprintf(_T("["));
		for(unsigned bit=0; bit<16; bit++)
			{
			WORD mask = (WORD)(1 << bit);
			// skip unused bits
			if((wiimote_state::buttons::ALL & mask) == 0)
				continue;

			const TCHAR* button_name = wiimote::ButtonNameFromBit[bit];
			bool		 pressed	 = ((remote.Button.Bits & mask) != 0);
			if(bit > 0) {
				CYAN; _tprintf(_T("|")); // seperator
				}
			if(pressed) {
				BRIGHT_WHITE; _tprintf(_T("%s")  , button_name);
				}
			else{
				WHITE       ; _tprintf(_T("%*s"), _tcslen(button_name), _T(""));
				}
			}
		WHITE; _tprintf(_T("]\n"));

		// Acceleration:
		CYAN ; _tprintf(_T("    Accel:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  X %+2.3f  Y %+2.3f  Z %+2.3f  \n"),
					remote.Acceleration.X,
					remote.Acceleration.Y,
					remote.Acceleration.Z);
	
		// Orientation estimate (shown red if last valid update is aging):
		CYAN ; _tprintf(_T("   Orient:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  UpdateAge %3u  "), remote.Acceleration.Orientation.UpdateAge);
		
		//  show if the last orientation update is considered out-of-date
		//   (using an arbitrary threshold)
		if(remote.Acceleration.Orientation.UpdateAge > 10)
			RED;
			
		_tprintf(_T("Pitch:%4ddeg  Roll:%4ddeg  Yaw:%4ddeg\n")
			     _T("                           (X %+.3f  Y %+.3f  Z %+.3f)      \n"),
				 (int)remote.Acceleration.Orientation.Pitch,
				 (int)remote.Acceleration.Orientation.Roll ,
				 remote.Acceleration.Orientation.X,
				 remote.Acceleration.Orientation.Y,
  				 remote.Acceleration.Orientation.Z);
				
		// IR:
		CYAN ; _tprintf(_T("       IR:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  Mode %s  "),
			((remote.IR.Mode == wiimote_state::ir::OFF     )? _T("OFF  ") :
			 (remote.IR.Mode == wiimote_state::ir::BASIC   )? _T("BASIC") :
			 (remote.IR.Mode == wiimote_state::ir::EXTENDED)? _T("EXT. ") :
															  _T("FULL ")));
		// IR dot sizes are only reported in EXTENDED IR mode (FULL isn't supported yet)
		bool dot_sizes = (remote.IR.Mode == wiimote_state::ir::EXTENDED);

		for(unsigned index=0; index<4; index++)
			{
			wiimote_state::ir::dot &dot = remote.IR.Dot[index];
			
			if(!remote.IsBalanceBoard()) WHITE;
			_tprintf(_T("%u: "), index);

			if(dot.bVisible) {
				WHITE; _tprintf(_T("Seen       "));
				}
			else{
				RED  ; _tprintf(_T("Not seen   "));
				}

			_tprintf(_T("Size"));
			if(dot_sizes)
				 _tprintf(_T("%3d "), dot.Size);
			else{
				RED; _tprintf(_T(" n/a"));
				if(dot.bVisible) WHITE;
				}

			_tprintf(_T("  X %.3f  Y %.3f\n"), dot.X, dot.Y);
			
			if(index < 3)
				_tprintf(_T("                        "));
			}

		// Speaker:
		CYAN ; _tprintf(_T("  Speaker:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  %s | %s    "), (remote.Speaker.bEnabled? _T("On ") :
															    _T("Off")),
									  (remote.Speaker.bMuted  ? _T("Muted") :
																_T("     ")));
		if(!remote.Speaker.bEnabled || remote.Speaker.bMuted)
			RED;
		else//if(remote.IsPlayingAudio()) BRIGHT_WHITE; else WHITE;
			WHITE;
		_tprintf(_T("Frequency %4u Hz   Volume 0x%02x\n"),
				 wiimote::FreqLookup[remote.Speaker.Freq],
				 remote.Speaker.Volume);
		
		// -- Extensions --:
		CYAN ; _tprintf(_T("__________\n  Extnsn.:  "));
		switch(remote.ExtensionType)
			{
			case wiimote_state::NONE:
				{
				RED;
				_tprintf(_T("None                                                             \n"));
				_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
				}
				break;
			
			case wiimote_state::PARTIALLY_INSERTED:
				{
				BRIGHT_RED;
				_tprintf(_T("Partially Inserted                                               \n"));
				_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
				}
				break;
			
			// -- Nunchuk --
			case wiimote_state::NUNCHUK:
				{
				BRIGHT_WHITE; _tprintf(_T("Nunchuk   "));

				// Buttons:
				CYAN		; _tprintf(_T("Buttons: ")); WHITE; _tprintf(_T("["));
				BRIGHT_WHITE; _tprintf(remote.Nunchuk.C? _T("C") : _T(" "));
				CYAN		; _tprintf(_T("|"));
				BRIGHT_WHITE; _tprintf(remote.Nunchuk.Z? _T("Z") : _T(" "));
				WHITE		; _tprintf(_T("]   "));
				// Joystick:
				CYAN		; _tprintf(_T("Joystick:  "));
				WHITE		; _tprintf(_T("X %+2.3f  Y %+2.3f\n"),
									   remote.Nunchuk.Joystick.X,
									   remote.Nunchuk.Joystick.Y);
				// Acceleration:
				CYAN		; _tprintf(_T("    Accel:"));
				WHITE		; _tprintf(_T("  X %+2.3f  Y %+2.3f  Z %+2.3f  \n"),
									   remote.Nunchuk.Acceleration.X,
									   remote.Nunchuk.Acceleration.Y,
									   remote.Nunchuk.Acceleration.Z);
				
				// Orientation estimate (shown red if last valid update is aging):
				CYAN		; _tprintf(_T("   Orient:"));
				WHITE		; _tprintf(_T("  UpdateAge %3u  "),
								remote.Nunchuk.Acceleration.Orientation.UpdateAge);
				//  show if the last orientation update is aging
				if(remote.Nunchuk.Acceleration.Orientation.UpdateAge > 10)
					RED;
				_tprintf(_T("Pitch %4ddeg  Roll %4ddeg  \n")
					     _T("                           (X %+.2f  Y %+.2f  Z %+.2f)      \n"),
						 (int)remote.Nunchuk.Acceleration.Orientation.Pitch,
						 (int)remote.Nunchuk.Acceleration.Orientation.Roll ,
						 remote.Nunchuk.Acceleration.Orientation.X,
						 remote.Nunchuk.Acceleration.Orientation.Y,
  						 remote.Nunchuk.Acceleration.Orientation.Z);
				}
				break;

			// -- Classic Controller --
			case wiimote_state::CLASSIC:
			case wiimote_state::GH3_GHWT_GUITAR:
			case wiimote_state::GHWT_DRUMS:
				{
				BRIGHT_WHITE;
				// the Guitar Hero controller is just a classic controller with
				//  another ID
				if(remote.ExtensionType == wiimote_state::CLASSIC)
					_tprintf(_T("Classic Controller   "));
				else if(remote.ExtensionType == wiimote_state::GH3_GHWT_GUITAR)
					_tprintf(_T("GH3/GHWT Guitar      "));
				else
					_tprintf(_T("GHWT Drums           "));
				
				// L: Joystick/Trigger
				WHITE; _tprintf(_T("L:  "));
				CYAN ; _tprintf(_T("Joy "));
				WHITE; _tprintf(_T("X %+2.3f  Y %+2.3f  "),
								remote.ClassicController.JoystickL.X,
								remote.ClassicController.JoystickL.Y);
				CYAN ; _tprintf(_T("Trig "));
				WHITE; _tprintf(_T("%+2.3f\n"),
								remote.ClassicController.TriggerL);
				// R: Joystick/Trigger
				WHITE; _tprintf(_T("                                 R:  "));
				CYAN ; _tprintf(_T("Joy "));
				WHITE; _tprintf(_T("X %+2.3f  Y %+2.3f  "),
								remote.ClassicController.JoystickR.X,
								remote.ClassicController.JoystickR.Y);
				CYAN ; _tprintf(_T("Trig "));
				WHITE; _tprintf(_T("%+2.3f\n"),
								remote.ClassicController.TriggerR);

				// Buttons:
				CYAN; _tprintf(_T("  Buttons: ")); WHITE; _tprintf(_T("["));
				for(unsigned bit=0; bit<16; bit++)
					{
					WORD mask = (WORD)(1 << bit);
					// skip unused bits
					if((wiimote_state::classic_controller::buttons::ALL & mask) == 0)
						continue;

					const TCHAR* button_name = wiimote::ClassicButtonNameFromBit[bit];
					const TCHAR* seperator	 = (bit==0)? _T("") : _T("|");
					bool		 pressed	 = ((remote.ClassicController.Button.Bits & mask) != 0);
					CYAN; _tprintf(seperator);
					if(pressed) {
						BRIGHT_WHITE; _tprintf(_T("%s")  , button_name);
						}
					else{
						WHITE	; _tprintf(_T("%*s"), _tcslen(button_name), _T(""));
						}
					}
				WHITE; _tprintf(_T("]"));
				}
				break;

			case wiimote_state::BALANCE_BOARD:
				{
				BRIGHT_WHITE; _tprintf(_T("Balance Board"));

				// Weights:
				CYAN ; _tprintf(_T("   Weight: "));
				WHITE; _tprintf(_T("TL    "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.TopL);
				CYAN ; _tprintf(_T(" kg")); WHITE; ;_tprintf(_T("  TR "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.TopR);
				CYAN;  _tprintf(_T(" kg\n")); WHITE;
					   _tprintf(_T("                                    BL    "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.BottomL);
				CYAN;  _tprintf(_T(" kg")); WHITE; _tprintf(_T("  BR "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.BottomR);
				CYAN;  _tprintf(_T(" kg \n")); WHITE;
					   _tprintf(_T("                                    Total "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.Total);
				CYAN;  _tprintf(_T(" kg"));
				}
				break;

			case wiimote_state::MOTION_PLUS:
				{
				BRIGHT_WHITE; _tprintf(_T("Motion Plus"));

				CYAN ; _tprintf(_T("    Raw: "));
				WHITE; _tprintf(_T("Yaw: %04hx  ")   , remote.MotionPlus.Raw.Yaw);
				WHITE; _tprintf(_T("Pitch: %04hx  ") , remote.MotionPlus.Raw.Pitch);
				WHITE; _tprintf(_T("Roll: %04hx  \n"), remote.MotionPlus.Raw.Roll);
				CYAN ; _tprintf(_T("                         Float: "));
				WHITE; _tprintf(_T("  %8.3fdeg")     , remote.MotionPlus.Speed.Yaw);
				WHITE; _tprintf(_T("  %8.3fdeg")   , remote.MotionPlus.Speed.Pitch);
				WHITE; _tprintf(_T(" %8.3fdeg\n")   , remote.MotionPlus.Speed.Roll);
				_tprintf(BLANK_LINE BLANK_LINE);
//Sleep(500);
				}
				break;
			}
  		}


	// disconnect (auto-happens on wiimote destruction anyway, but let's play nice)
	remote.Disconnect();
	Beep(1000, 200);

	BRIGHT_WHITE; // for automatic 'press any key to continue' msg
	CloseHandle(console);

	return 0;
	}
Exemplo n.º 2
0
int main()
{
	SetConsoleTitle(_T("- WiiRemoteYourself! - Demo: "));
	void* console = GetStdHandle(STD_OUTPUT_HANDLE);
	PrintTitle(console);

	WiiRemoteSample sineSample, daisySample;
	if (!WiiRemote::Load16BitMonoSampleRAW("1kSine16 (3130).raw", true, SpeakerFrequency::Frequency3130Hz, sineSample))
	{
		printf_s("\r  ** can't find 'sine16 (3130).raw' - (sample won't work!) **");
		printf_s("\r");
		printf_s(BLANK_LINE);
	}
	if (!WiiRemote::Load16BitMonoSampleWAV("Daisy16 (3130).wav", daisySample))
	{
		printf_s("\r  ** can't find 'Daisy16 (3130).wav' - (sample won't work!) **");
		printf_s("\r");
		printf_s(BLANK_LINE);
	}
	WiiRemote remote;
	remote.ChangedCallback = OnStateChange;
	remote.CallbackTriggerFlags = static_cast<StateChangeFlags>(
		static_cast<int>(StateChangeFlags::Connected) |
		static_cast<int>(StateChangeFlags::ExtensionChanged) |
		static_cast<int>(StateChangeFlags::MotionPlusChanged));

reconnect:
	COORD position = { 0, 6 };
	static const char* waitString[] = { ".  ", "..  ", "..." };
	unsigned int count = 0;
	SetConsoleCursorPosition(console, position);
	SetConsoleTextAttribute(console, WHITE);
	printf_s("  Looking for a WiiRemote     ");
	while (!remote.Connect())
	{
		printf_s("\b\b\b\b%s ", waitString[count % 3]);
		count++;
	}
	remote.SetLEDs(0x0F);
	SetConsoleTextAttribute(console, BRIGHT_CYAN);
	printf_s("\b\b\b\b... connected!");
	if (remote.IsBalanceBoard())
	{
		SetConsoleTextAttribute(console, BRIGHT_WHITE);
		printf_s("  (Balance Board)");
	}
	Sleep(2000);

	COORD cursorPosition = { 0, 6 };
	printf_s("\n\n");
	WiiRemote* extraMotes[7] = { nullptr };
	auto detected = 0;
	while (detected < 7)
	{
		WiiRemote* next = new WiiRemote();
		if (!next->Connect())
			break;
		extraMotes[detected++] = next;
		SetConsoleTextAttribute(console, WHITE);
		printf_s("    also found WiiRemote ");
		SetConsoleTextAttribute(console, BRIGHT_GREEN);
		if (next->IsBalanceBoard())
		{
			SetConsoleTextAttribute(console, WHITE);
			printf_s("  (Balance Board)");
		}
		printf_s("\n\n");
		Sleep(500);
	}
	SetConsoleTextAttribute(console, WHITE);
	printf_s(((detected == 7) ? "    (can't detect any more)." : "    (no more found.)"));
	Sleep(2000);
	for (auto index = 0; index < detected; index++)
		delete extraMotes[index];
	SetConsoleCursorPosition(console, cursorPosition);
	SetConsoleTextAttribute(console, BRIGHT_WHITE);
	printf_s("\r  -- TRY: B = rumble, A = square, 1 = sine, 2 = daisy, Home = Exit --\n");
	auto lastRumbleTime = timeGetTime();
	auto lastLEDTime = timeGetTime();
	auto RumbleText = true;
	auto litLED = 0;
	while (!remote.Buttons.Home())
	{
		while (remote.RefreshState() == StateChangeFlags::NoChange)
			Sleep(1);
		cursorPosition.Y = 8;
		SetConsoleCursorPosition(console, cursorPosition);
		if (remote.ConnectionLost())
		{
			SetConsoleTextAttribute(console, BRIGHT_RED);
			printf_s("   *** connection lost! ***\n");
			printf_s(BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE);
			Sleep(2000);
			COORD position = { 0, 6 };
			SetConsoleCursorPosition(console, position);
			printf_s(BLANK_LINE BLANK_LINE BLANK_LINE);
			goto reconnect;
		}
		remote.SetRumble(remote.Buttons.B());
		static auto lastMinus = false;
		if (remote.Buttons.Minus() && !lastMinus && ((remote.ExtensionType == ExtensionType::MotionPlus) || (remote.ExtensionType == ExtensionType::WiiRemotePlus)))
			remote.DisableMotionPlus();
		lastMinus = remote.Buttons.Minus();
		static auto lastA = false, lastOne = false, lastTwo = false;
		if (!remote.IsBalanceBoard())
		{
			ON_PRESS_RELEASE(A, remote.PlaySquareWave(SpeakerFrequency::Frequency3130Hz, 0x20), remote.EnableSpeaker(false));
			ON_PRESS_RELEASE(One, remote.PlaySample(sineSample), remote.EnableSpeaker(false));
			ON_PRESS_RELEASE(Two, remote.PlaySample(daisySample), remote.EnableSpeaker(false));
		}
		SetConsoleTextAttribute(console, CYAN);
		printf_s("  Bettery: ");
		remote.bBatteryDrained ?
			SetConsoleTextAttribute(console, BRIGHT_RED) :
			(remote.BatteryPercent >= 30 ? SetConsoleTextAttribute(console, BRIGHT_GREEN) : SetConsoleTextAttribute(console, BRIGHT_YELLOW));
		printf_s("%3u%%  ", remote.BatteryPercent);
		const auto currentTime = timeGetTime();
		if ((currentTime - lastLEDTime) >= 1000)
		{
			remote.SetLEDs(static_cast<unsigned char>(1 << litLED));
			litLED = (++litLED) % 4;
			lastLEDTime = timeGetTime();
		}
		SetConsoleTextAttribute(console, CYAN);
		printf_s("LEDs: ");
		SetConsoleTextAttribute(console, WHITE);
		printf_s("[");
		for (auto led = 0; led < 4; led++)
		{
			if (remote.LED.Lit(led))
			{
				SetConsoleTextAttribute(console, BRIGHT_CYAN);
				printf_s("*");
			}
			else
			{
				SetConsoleTextAttribute(console, WHITE);
				printf_s("-");
			}
		}
		SetConsoleTextAttribute(console, WHITE);
		printf_s("] ");
		if (remote.bRumble)
		{
			SetConsoleTextAttribute(console, BRIGHT_WHITE);
			printf_s(RumbleText ? " RUMBLE" : "RUMBLE ");
			if ((currentTime - lastRumbleTime) >= 110)
			{
				RumbleText = !RumbleText;
				lastRumbleTime = currentTime;
			}
		}
		else
			printf_s("       ");
		SetConsoleTextAttribute(console, CYAN);
		printf_s("      using %s\n", (remote.IsUsingHIDWrites() ? "HID writes" : "WriteFile()"));
		printf_s("      ID: ");
		SetConsoleTextAttribute(console, YELLOW);
		printf_s("%I64u", remote.UniqueID);
		SetConsoleTextAttribute(console, CYAN);
		printf_s("      ID2: ");
		SetConsoleTextAttribute(console, WHITE);
		printf_s("%I64u\n", remote.UniqueID2);
		SetConsoleTextAttribute(console, CYAN);
		printf_s("  Buttons: ");
		SetConsoleTextAttribute(console, WHITE);
		printf_s("[");
		for (auto bit = 0; bit < 16; bit++)
		{
			const auto mask = static_cast<unsigned short>(1 << bit);
			if ((static_cast<unsigned short>(WiiRemoteButtons::Mask::All) & mask) == 0)
				continue;
			const auto buttonName = WiiRemote::GetButtonNameFromBit(bit);
			const auto pressed = ((remote.Buttons.Bits & mask) != 0);
			if (bit > 0)
			{
				SetConsoleTextAttribute(console, CYAN);
				printf_s("|");
			}
			if (pressed)
			{
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s("%s", buttonName);
			}
			else
			{
				SetConsoleTextAttribute(console, WHITE);
				printf_s("%*s", static_cast<int>(strlen(buttonName)), "");
			}
		}
		SetConsoleTextAttribute(console, WHITE);
		printf_s("]\n");
		SetConsoleTextAttribute(console, CYAN);
		printf_s("     Accel:");
		remote.IsBalanceBoard() ? SetConsoleTextAttribute(console, RED) : SetConsoleTextAttribute(console, WHITE);
		printf_s("  X %+2.3f  Y %+2.3f  Z %+2.3f  \n", remote.Acceleration.Data.X, remote.Acceleration.Data.Y, remote.Acceleration.Data.Z);
		SetConsoleTextAttribute(console, CYAN);
		printf_s("   Orient:");
		SetConsoleTextAttribute(console, remote.IsBalanceBoard() ? RED : WHITE);
		printf_s("UpdateAge %3u  ", remote.Acceleration.Orientation.UpdateAge);
		if (remote.Acceleration.Orientation.UpdateAge > 10)
			SetConsoleTextAttribute(console, RED);
		printf_s("Pitch: %4ddeg  Roll:%4ddeg  \n                           (X %+.3f  Y %+.3f  Z %+.3f)      \n",
			static_cast<int>(remote.Acceleration.Orientation.Rotation.Pitch), static_cast<int>(remote.Acceleration.Orientation.Rotation.Roll),
			remote.Acceleration.Orientation.Data.X, remote.Acceleration.Orientation.Data.Y, remote.Acceleration.Orientation.Data.Z);
		SetConsoleTextAttribute(console, CYAN);
		printf_s("      IR:");
		remote.IsBalanceBoard() ? SetConsoleTextAttribute(console, RED) : SetConsoleTextAttribute(console, WHITE);
		printf_s("  Mode %s   ", ((remote.IR.Mode == IRMode::Off) ? "OFF  " : ((remote.IR.Mode == IRMode::Basic) ? "BASIC" :
			((remote.IR.Mode == IRMode::Extended) ? "EXT. " : "FULL "))));
		const auto dotSize = (remote.IR.Mode == IRMode::Extended);
		for (auto index = 0; index < 4; index++)
		{
			auto& dot = remote.IR.Dots[index];
			if (!remote.IsBalanceBoard())
				SetConsoleTextAttribute(console, WHITE);
			printf_s("%u: ", index);
			if (dot.Visible)
			{
				SetConsoleTextAttribute(console, WHITE);
				printf_s("Seen       ");
			}
			else
			{
				SetConsoleTextAttribute(console, RED);
				printf_s("Not Seen   ");
			}
			printf_s("Size");
			if (dotSize)
			{
				printf_s("%3d ", dot.Size);
			}
			else
			{
				SetConsoleTextAttribute(console, RED);
				printf_s(" n/a");
				if (dot.Visible)
					SetConsoleTextAttribute(console, WHITE);
			}
			printf_s("  X %.3f  Y %.3f\n", dot.Data.X, dot.Data.Y);
			if (index < 3)
				printf_s("                        ");
		}
		SetConsoleTextAttribute(console, CYAN);
		printf_s("  Speaker:");
		remote.IsBalanceBoard() ? SetConsoleTextAttribute(console, RED) : SetConsoleTextAttribute(console, WHITE);
		printf_s("  %s | %s    ", (remote.Speaker.Enabled ? "On " : "Off"), (remote.Speaker.Muted ? "Muted" : "     "));
		if (!remote.Speaker.Enabled || remote.Speaker.Muted)
			SetConsoleTextAttribute(console, RED);
		else
			SetConsoleTextAttribute(console, WHITE);
		printf_s("Frequency %4u Hz   Volume 0x%02x\n", WiiRemote::GetFrequencyLookup(static_cast<int>(remote.Speaker.Frequency)), remote.Speaker.Volume);
		SetConsoleTextAttribute(console, CYAN);
		printf_s("__________\n  Extnsn.:  ");
		switch (remote.ExtensionType)
		{
		case ExtensionType::None:
			SetConsoleTextAttribute(console, RED);
			printf_s("None\n");
			printf_s(BLANK_LINE BLANK_LINE BLANK_LINE);
			break;
		case ExtensionType::PartiallyInserted:
			SetConsoleTextAttribute(console, BRIGHT_RED);
			printf_s("Partially Inserted\n");
			printf_s(BLANK_LINE BLANK_LINE BLANK_LINE);
			break;
		default:
			if (remote.ExtensionType == ExtensionType::Nunchuk)
			{
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s("Nunchuk   ");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Buttons: ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("[");
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s(remote.Nunchuk.C ? "C" : " ");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("|");
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s(remote.Nunchuk.Z ? "Z" : " ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("]   ");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Joystick:  ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("X %+2.3f  Y %+2.3f\n", remote.Nunchuk.Joystick.Data.X, remote.Nunchuk.Joystick.Data.Y);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("     Accel:");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("   X %+2.3f  Y %+2.3f  Z %+2.3f  \n", remote.Nunchuk.Acceleration.Data.X, remote.Nunchuk.Acceleration.Data.Y, remote.Nunchuk.Acceleration.Data.Z);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("   Orient:");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("   UpdateAge %3u  ", remote.Nunchuk.Acceleration.Orientation.UpdateAge);
				if (remote.Nunchuk.Acceleration.Orientation.UpdateAge > 10)
					SetConsoleTextAttribute(console, RED);
				printf_s("Pitch %4ddeg  Roll %4ddeg  \n                           (X %+.2f  Y %+.2f  Z %+.2f)     \n",
					static_cast<int>(remote.Nunchuk.Acceleration.Orientation.Rotation.Pitch), static_cast<int>(remote.Nunchuk.Acceleration.Orientation.Rotation.Roll),
					remote.Nunchuk.Acceleration.Orientation.Data.X, remote.Nunchuk.Acceleration.Orientation.Data.Y, remote.Nunchuk.Acceleration.Orientation.Data.Z);
			}
			if (remote.ExtensionType == ExtensionType::Classic || remote.ExtensionType == ExtensionType::GH3GhwtGuitar || remote.ExtensionType == ExtensionType::GhwtDrums)
			{
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				if (remote.ExtensionType == ExtensionType::Classic)
					printf_s("Classic Controller   ");
				else if (remote.ExtensionType == ExtensionType::GH3GhwtGuitar)
					printf_s("GH3/GHWT Guitar      ");
				else
					printf_s("GHWT Drums           ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("L:  ");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Joy ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("X %+2.3f  Y %+2.3f  ", remote.ClassicController.JoystickL.Data.X, remote.ClassicController.JoystickL.Data.Y);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Trigger ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("%+2.3f\n", remote.ClassicController.TriggerL);
				printf_s("                                 R:  ");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Joy ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("X %+2.3f  Y %+2.3f  ", remote.ClassicController.JoystickR.Data.X, remote.ClassicController.JoystickR.Data.Y);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("Trigger ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("%+2.3f\n", remote.ClassicController.TriggerR);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("  Buttons: ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("[");
				for (auto bit = 0; bit < 16; bit++)
				{
					const auto mask = static_cast<unsigned short>(1 << bit);
					if ((static_cast<unsigned short>(WiiRemoteButtons::Mask::All) & mask) == 0)
						continue;
					const auto buttonName = WiiRemote::GetClassicButtonNameFromBit(bit);
					const auto seperator = (bit == 0) ? "" : "|";
					const auto pressed = ((static_cast<unsigned short>(remote.ClassicController.Buttons.Bits) & mask) != 0);
					if (pressed)
					{
						SetConsoleTextAttribute(console, BRIGHT_WHITE);
						printf_s("%s", buttonName);
					}
					else
					{
						SetConsoleTextAttribute(console, WHITE);
						printf_s("%*s", static_cast<int>(strlen(buttonName)), "");
					}
				}
				SetConsoleTextAttribute(console, WHITE);
				printf_s("]");
			}
			if (remote.ExtensionType == ExtensionType::BalanceBoard)
			{
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s("Balance Board");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("   Weight: ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("TL    %6.2f", remote.BalanceBoard.Kg.TopL);
				SetConsoleTextAttribute(console, CYAN);
				printf_s(" Kg");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("  TR %6.2f", remote.BalanceBoard.Kg.TopR);
				SetConsoleTextAttribute(console, CYAN);
				printf_s(" Kg\n");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("                                    BL    %6.2f", remote.BalanceBoard.Kg.BottomL);
				SetConsoleTextAttribute(console, CYAN);
				printf_s(" Kg");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("  BR %6.2f", remote.BalanceBoard.Kg.BottomR);
				SetConsoleTextAttribute(console, CYAN);
				printf_s(" Kg \n");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("                                    Total %6.2f", remote.BalanceBoard.Kg.Total);
				SetConsoleTextAttribute(console, CYAN);
				printf_s(" Kg");
			}
			if (remote.ExtensionType == ExtensionType::MotionPlus || remote.ExtensionType == ExtensionType::WiiRemotePlus)
			{
				SetConsoleTextAttribute(console, BRIGHT_WHITE);
				printf_s("Motion Plus");
				SetConsoleTextAttribute(console, CYAN);
				printf_s("    Raw: ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("Yaw: %04hx  Pitch: %04hx  Roll: %04hx  \n", remote.MotionPlus.Raw.Yaw, remote.MotionPlus.Raw.Pitch, remote.MotionPlus.Raw.Roll);
				SetConsoleTextAttribute(console, CYAN);
				printf_s("                         Float: ");
				SetConsoleTextAttribute(console, WHITE);
				printf_s("   %8.3fdeg  %8.3fdeg  %8.3fdeg\n", remote.MotionPlus.Speed.Yaw, remote.MotionPlus.Speed.Pitch, remote.MotionPlus.Speed.Roll);
				printf_s(BLANK_LINE BLANK_LINE);
			}
			break;
		}
	}
	remote.Disconnect();
	SetConsoleTextAttribute(console, BRIGHT_WHITE);
	CloseHandle(console);
	return 0;
}