diff options
Diffstat (limited to 'tracker-pt/wiiyourself/wiimote.h')
-rw-r--r-- | tracker-pt/wiiyourself/wiimote.h | 495 |
1 files changed, 0 insertions, 495 deletions
diff --git a/tracker-pt/wiiyourself/wiimote.h b/tracker-pt/wiiyourself/wiimote.h deleted file mode 100644 index 1db2c098..00000000 --- a/tracker-pt/wiiyourself/wiimote.h +++ /dev/null @@ -1,495 +0,0 @@ -// _______________________________________________________________________________ -// -// - WiiYourself! - native C++ Wiimote library v1.15 -// (c) gl.tter 2007-10 - http://gl.tter.org -// -// see License.txt for conditions of use. see History.txt for change log. -// _______________________________________________________________________________ -// -// wiimote.h (tab = 4 spaces) - -#ifdef _MSC_VER // VC -# pragma once -#endif - -#ifndef _WIIMOTE_H -# define _WIIMOTE_H - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <tchar.h> // auto Unicode/Ansi support -#include <queue> // for HID write method -#include <list> // for state recording - -#ifndef QWORD - typedef unsigned __int64 QWORD; -#endif - -#ifdef _MSC_VER // VC-specific: _DEBUG build only _ASSERT() sanity checks -# include <crtdbg.h> -#elif defined(__MINGW32__) // define NDEBUG to disable assert -# include <assert.h> -# define _ASSERT assert -#else -# define _ASSERT(x) ((void)0) // (add your compiler's implementation if you like) -#endif - -#ifdef SWIGWRAPPER // Python Wrapper -#include "Python/wiimote_state.i" -#else -#include "wiimote_state.h" -#endif - -// configs: -//#define USE_DYNAMIC_HIDQUEUE // deprecated - -// we request periodic status report updates to refresh the battery level -// and to detect connection loss (through failed writes) -#define REQUEST_STATUS_EVERY_MS 1000 -#define DETECT_MPLUS_EVERY_MS 1000 -#define DETECT_MPLUS_COUNT 1 // # of tries in quick succession - -// all threads (read/parse, audio streaming, async rumble...) use this priority -#define WORKER_THREAD_PRIORITY THREAD_PRIORITY_HIGHEST - - // internals -#define WIIYOURSELF_VERSION_MAJOR 1 -#define WIIYOURSELF_VERSION_MINOR1 1 -#define WIIYOURSELF_VERSION_MINOR2 5 -//#define WIIYOURSELF_VERSION_BETA // not defined for non-beta releases -#define WIIYOURSELF_VERSION_STR _T("1.15") - -// array sizes -#define TOTAL_BUTTON_BITS 16 // Number of bits for (Classic)ButtonNameFromBit[] -#define TOTAL_FREQUENCIES 10 // Number of frequencies (see speaker_freq[]) - - // clarity -typedef HANDLE EVENT; - - -// state data changes can be signalled to the app via a callback. Set the wiimote -// object's 'ChangedCallback' any time to enable them, or alternatively inherit -// from the wiimote object and override the ChangedNotifier() virtual method. - -// of flags indicating which state has changed since the last callback. -typedef void (*state_changed_callback) (class wiimote &owner, - state_change_flags changed, - const wiimote_state &new_state); - -// internals -typedef BOOLEAN (__stdcall *hidwrite_ptr)(HANDLE HidDeviceObject, - PVOID ReportBuffer, - ULONG ReportBufferLength); - -// (global due to Python wrapper) -struct wiimote_state_event { - DWORD time_ms; // system timestamp in milliseconds - wiimote_state state; - }; - -// wiimote class - connects and manages a wiimote and its optional extensions -// (Nunchuk/Classic Controller), and exposes their state -class wiimote : public wiimote_state - { - public: - wiimote (); - virtual ~wiimote (); - - public: - // these can be used to identify Connect()ed wiimote objects (if both - // are unconnected they will pass the compare as their handles are invalid) - inline bool operator == (const wiimote& remote) - { return Handle == remote.Handle; } - inline bool operator != (const wiimote& remote) - { return Handle != remote.Handle; } - - // wiimote data input mode (use with SetReportType()) - // (only enable what you need to save battery power) - enum input_report - { - // combinations if buttons/acceleration/IR/Extension data - IN_BUTTONS = 0x30, - IN_BUTTONS_ACCEL = 0x31, - IN_BUTTONS_ACCEL_IR = 0x33, // reports IR EXTENDED data (dot sizes) - IN_BUTTONS_ACCEL_EXT = 0x35, - IN_BUTTONS_ACCEL_IR_EXT = 0x37, // reports IR BASIC data (no dot sizes) - IN_BUTTONS_BALANCE_BOARD = 0x32, // must use this for the balance board - }; - // string versions - static const TCHAR* ReportTypeName []; - - - public: // convenience accessors: - inline bool IsConnected () const { return bStatusReceived; } - // if IsConnected() unexpectedly returns false, connection was probably lost - inline bool ConnectionLost () const { return bConnectionLost; } - inline bool IsBalanceBoard () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::BALANCE_BOARD)); } - inline bool NunchukConnected () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::NUNCHUK)); } - inline bool ClassicConnected () const { return (Internal.bExtension && - (Internal.ExtensionType==wiimote_state::CLASSIC)); } - inline bool MotionPlusConnected () const { return bMotionPlusDetected; } - inline bool MotionPlusEnabled () const { return bMotionPlusEnabled; } - inline bool MotionPlusHasExtension() const { return bMotionPlusExtension; } - inline bool IsPlayingAudio () const { return (Internal.Speaker.Freq && - Internal.Speaker.Volume); } - inline bool IsPlayingSample () const { return IsPlayingAudio() && - (CurrentSample != NULL); } - inline bool IsUsingHIDwrites () const { return bUseHIDwrite; } - inline bool IsRecordingState () const { return Recording.bEnabled; } - - static inline unsigned TotalConnected() { return _TotalConnected; } - - - public: // data - QWORD UniqueID; // constructed from device-specific calibration info. - // Note this is not guaranteed to be truly unique - // as several devices may contain the same calibration - // vluaes - but unique amongst a small number of - // devices. -#ifdef ID2_FROM_DEVICEPATH - QWORD UniqueID2; // (low-reliabilty, left for reference) - // constructed from the 'device path' string (as - // reported by the OS/stack). This is hopefully - // unique as long as the devices remain installed - // (or at least paired). -#endif - // optional callbacks - set these to your own fuctions (if required) - state_changed_callback ChangedCallback; - // you can avoid unnecessary callback overhead by specifying a mask - // of which state changes should trigger them (default is any) - state_change_flags CallbackTriggerFlags; - // alternatively, inherit from this class and override this virtual function: - virtual void ChangedNotifier (state_change_flags changed, - const wiimote_state &new_state) {}; - - // get the button name from its bit index (some bits are unused) - static const TCHAR* ButtonNameFromBit [TOTAL_BUTTON_BITS]; - static const TCHAR* GetButtonNameFromBit (unsigned index) - { - _ASSERT(index < TOTAL_BUTTON_BITS); - if(index >= TOTAL_BUTTON_BITS) - return _T("[invalid index]"); - return ButtonNameFromBit[index]; - } - - // same for the Classic Controller - static const TCHAR* ClassicButtonNameFromBit [TOTAL_BUTTON_BITS]; - static const TCHAR* GetClassicButtonNameFromBit (unsigned index) - { - _ASSERT(index < TOTAL_BUTTON_BITS); - if(index >= TOTAL_BUTTON_BITS) - return _T("[invalid index]"); - return ClassicButtonNameFromBit[index]; - } - - // get the frequency from speaker_freq enum - static const unsigned FreqLookup [TOTAL_FREQUENCIES]; - static const unsigned GetFreqLookup (unsigned index) - { - _ASSERT(index < TOTAL_FREQUENCIES); - if(index >= TOTAL_FREQUENCIES) - return 0; - return FreqLookup[index]; - } - - public: // methods - // call Connect() first - returns true if wiimote was found & enabled - // - 'wiimote_index' specifies which *installed* (not necessarily - // *connected*) wiimote should be tried (1 = first, 2 = 2nd etc). - // if you just want the first *available* wiimote that isn't already - // in use, pass in FIRST_AVAILABLE (default). - // - 'force_hidwrites' forces HID output method (it's auto-selected - // when needed and less efficient, so only force for testing). - static const unsigned FIRST_AVAILABLE = 0xffffffff; - bool Connect (unsigned wiimote_index = FIRST_AVAILABLE, - bool force_hidwrites = false); - // disconnect from the controller and stop reading data from it - void Disconnect (); - // set wiimote reporting mode (call after Connnect()) - // continous = true forces the wiimote to send constant updates, even when - // nothing has changed. - // = false only sends data when something has changed (note that - // acceleration data will cause frequent updates anyway as it - // jitters even when the wiimote is stationary) - void SetReportType (input_report type, bool continuous = false); - - // toggle the MotionPlus extension. Call MotionPlusDetected() first to - // see if it's attached. Unlike normal extensions, the MotionPlus does - // not report itself as one until enabled. Once done, it then replaces - // any standard extension attached to it, so be sure to disable it - // if you want to read those (it's not currently known of both can - // be read simultaneously). - bool EnableMotionPlus (); - bool DisableMotionPlus (); - - // this is used to remove unwanted 'at rest' offsets, currently only from - // the Balance Board. make sure there is no weight on the board before - // calling this. it reads the current sensor values and then removes them - // offsets from all subsequent KG and LB state values (the 'raw' values - // are never modified). - void CalibrateAtRest (); - // NOTE: the library automatically calls this when the first weight values - // come in after Connect()ion, but if the device wasn't at rest at - // the time the app can call it again later. - - // to read the state via polling (reading the public state data direct from - // the wiimote object) you must call RefreshState() at the top of every pass. - // returns a combination of flags to indicate which state (if any) has - // changed since the last call. - state_change_flags RefreshState (); - - // reset the wiimote (changes report type to non-continuous buttons-only, - // clears LEDs & rumble, mutes & disables speaker) - void Reset (); - // set/clear the wiimote LEDs - void SetLEDs (BYTE led_bits); // bits 0-3 are valid - // set/clear rumble - void SetRumble (bool on); - // alternative - rumble for a fixed amount of time (asynchronous) - void RumbleForAsync (unsigned milliseconds); - - // *experimental* speaker support: - bool MuteSpeaker (bool on); - bool EnableSpeaker (bool on); - bool PlaySquareWave (speaker_freq freq, BYTE volume = 0x40); - // note: PlaySample currently streams from the passed-in wiimote_sample - - // don't delete it until playback has stopped. - bool PlaySample (const wiimote_sample &sample, - BYTE volume = 0x40, - speaker_freq freq_override = FREQ_NONE); - - // 16bit mono sample loading/conversion to native format: - // .wav sample - static bool Load16bitMonoSampleWAV (const TCHAR* filepath, - wiimote_sample &out); - // raw 16bit mono audio data (can be signed or unsigned) - static bool Load16BitMonoSampleRAW (const TCHAR* filepath, - bool _signed, - speaker_freq freq, - wiimote_sample &out); - // converts a 16bit mono sample array to a wiimote_sample - static bool Convert16bitMonoSamples (const short* samples, - bool _signed, - DWORD length, - speaker_freq freq, - wiimote_sample &out); - - // state recording - records state snapshots to a 'state_history' supplied - // by the caller. states are timestamped and only added - // to the list when the specified state changes. -#ifndef SWIG // !Python Wrapper - typedef wiimote_state_event state_event; -#endif - typedef std::list<state_event> state_history; - static const unsigned UNTIL_STOP = 0xffffffff; - // - pass in a 'state_history' list, and don't destroy/change it until - // recording is stopped. note the list will be cleared first. - // - you can request a specific duration (and use IsRecordingState() to detect - // the end), or UNTIL_STOP. StopRecording() can be called either way. - // - you can use 'change trigger' to specify specific state changes that will - // trigger an insert into the history (others are then ignored). - void RecordState (state_history &events_out, - unsigned max_time_ms = UNTIL_STOP, - state_change_flags change_trigger = CHANGED_ALL); - void StopRecording (); - - - private: // methods - // start reading asynchronously from the controller - bool BeginAsyncRead (); - // request status update (battery level, extension status etc) - void RequestStatusReport (); - // read address or register from Wiimote asynchronously (the result is - // parsed internally whenever it arrives) - bool ReadAddress (int address, short size); - // write a single BYTE to a wiimote address or register - inline void WriteData (int address, BYTE data) { WriteData(address, 1, &data); } - // write a BYTE array to a wiimote address or register - void WriteData (int address, BYTE size, const BYTE* buff); - // callback when data is ready to be processed - void OnReadData (DWORD bytes_read); - // parse individual reports by type - int ParseInput (BYTE* buff); - // detects if MotionPlus is attached (it doesn't report as a normal - // extesnion until it is enabled) - void DetectMotionPlusExtensionAsync (); - // initializes an extension when plugged in. - void InitializeExtension (); - // parses a status report - int ParseStatus (BYTE* buff); - // parses the buttons - int ParseButtons (BYTE* buff); - // parses accelerometer data - int ParseAccel (BYTE* buff); - bool EstimateOrientationFrom(wiimote_state::acceleration &accel); - void ApplyJoystickDeadZones (wiimote_state::joystick &joy); - // parses IR data from report - int ParseIR (BYTE* buff); - // parses data from an extension. - int ParseExtension (BYTE* buff, unsigned offset); - // parses data returned from a read report - int ParseReadAddress (BYTE* buff); - // reads calibration information stored on Wiimote - void ReadCalibration (); - float GetBalanceValue(short sensor, short min, short mid, short max); - // turns on the IR sensor (the mode must match the reporting mode caps) - void EnableIR (wiimote_state::ir::mode mode); - // disables the IR sensor - void DisableIR (); - // writes a report to the Wiimote (NULL = use 'WriteBuff') - bool WriteReport (BYTE* buff); - bool StartSampleThread (); - // returns the rumble BYTE that needs to be sent with reports. - inline BYTE GetRumbleBit () const { return Internal.bRumble? 0x01 : 0x00; } - - // static thread funcs: - static unsigned __stdcall ReadParseThreadfunc (void* param); - static unsigned __stdcall AsyncRumbleThreadfunc (void* param); - static unsigned __stdcall SampleStreamThreadfunc(void* param); - static unsigned __stdcall HIDwriteThreadfunc (void* param); - - private: // data - // wiimote output comands - enum output_report - { - OUT_NONE = 0x00, - OUT_LEDs = 0x11, - OUT_TYPE = 0x12, - OUT_IR = 0x13, - OUT_SPEAKER_ENABLE = 0x14, - OUT_STATUS = 0x15, - OUT_WRITEMEMORY = 0x16, - OUT_READMEMORY = 0x17, - OUT_SPEAKER_DATA = 0x18, - OUT_SPEAKER_MUTE = 0x19, - OUT_IR2 = 0x1a, - }; - // input reports used only internally: - static const int IN_STATUS = 0x20; - static const int IN_READADDRESS = 0x21; - // wiimote device IDs: - static const int VID = 0x057e; // 'Nintendo' - static const int PID = 0x0306; // 'Wiimote' - // we could find this out the hard way using HID, but it's 22 - static const int REPORT_LENGTH = 22; - // wiimote registers - static const int REGISTER_CALIBRATION = 0x0016; - static const int REGISTER_IR = 0x4b00030; - static const int REGISTER_IR_SENSITIVITY_1 = 0x4b00000; - static const int REGISTER_IR_SENSITIVITY_2 = 0x4b0001a; - static const int REGISTER_IR_MODE = 0x4b00033; - static const int REGISTER_EXTENSION_INIT1 = 0x4a400f0; - static const int REGISTER_EXTENSION_INIT2 = 0x4a400fb; - static const int REGISTER_EXTENSION_TYPE = 0x4a400fa; - static const int REGISTER_EXTENSION_CALIBRATION = 0x4a40020; - static const int REGISTER_BALANCE_CALIBRATION = 0x4a40024; - static const int REGISTER_MOTIONPLUS_DETECT = 0x4a600fa; - static const int REGISTER_MOTIONPLUS_INIT = 0x4a600f0; - static const int REGISTER_MOTIONPLUS_ENABLE = 0x4a600fe; - - HANDLE Handle; // read/write device handle - OVERLAPPED Overlapped; // for async Read/WriteFile() IO - HANDLE ReadParseThread; // waits for overlapped reads & parses result - EVENT DataRead; // signals overlapped read complete - bool bUseHIDwrite; // alternative write method (less efficient - // but required for some BT stacks (eg. MS') - // HidD_SetOutputReport is only supported from XP onwards, so detect & - // load it dynamically: - static HMODULE HidDLL; - static hidwrite_ptr _HidD_SetOutputReport; - - volatile bool bStatusReceived; // for output method detection - volatile bool bConnectInProgress; // don't handle extensions until complete - volatile bool bInitInProgress; // stop regular requests until complete - volatile bool bEnablingMotionPlus; // for special init codepath - volatile bool bConnectionLost; // auto-Disconnect()s if set -volatile int MotionPlusDetectCount; // waiting for the result - volatile bool bMotionPlusDetected; - volatile bool bMotionPlusEnabled; - volatile bool bMotionPlusExtension;// detected one plugged into MotionPlus - volatile bool bCalibrateAtRest; // as soon as the first sensor values // come in after a Connect() call. - static unsigned _TotalCreated; - static unsigned _TotalConnected; - input_report ReportType; // type of data the wiimote delivers - // read buffer - BYTE ReadBuff [REPORT_LENGTH]; - // for polling: state is updated on a thread internally, and made only - // made public via RefreshState() - CRITICAL_SECTION StateLock; - wiimote_state Internal; - state_change_flags InternalChanged; // state changes since last RefreshState() - // periodic status report requests (for battery level and connection loss - // detection) - DWORD NextStatusTime; - DWORD NextMPlusDetectTime;// gap between motion plus detections - DWORD MPlusDetectCount; // # of detection tries in quick succesion - // async Hidd_WriteReport() thread - HANDLE HIDwriteThread; -#ifdef USE_DYNAMIC_HIDQUEUE - std::queue<BYTE*> HIDwriteQueue; -#else - // fixed-size queue (to eliminate glitches caused by frequent dynamic memory - // allocations) - struct hid - { - hid () : Queue(NULL), ReadIndex(0), WriteIndex(0) {} - - // Increase the static queue size if you get ASSERTs signalling an - // overflow (too many reports queued up before being sent by the write - // thread). These asserts are harmless though if caused as a result of - // loosing the wiimote connection (eg. battery runs out, or wiimote is - // unpaired by holding the power button). - // Note: MAX_QUEUE_ENTRIES _must_ be a power-of-2, as it - // uses index wraparound optimisations. - static const unsigned MAX_QUEUE_ENTRIES = 1<<7; - - inline bool IsEmpty() const { return (ReadIndex == WriteIndex); } - - bool Allocate () { // allocate memory (only when needed) - _ASSERT(!Queue); if(Queue) return true; - ReadIndex = WriteIndex = 0; - Queue = new queue_entry[MAX_QUEUE_ENTRIES]; - _ASSERT(Queue); return (Queue != NULL); - } - void Deallocate () { - if(!Queue) return; - delete[] Queue; Queue = NULL; - ReadIndex = WriteIndex = 0; - } - - struct queue_entry - { - queue_entry() { memset(Report, 0, sizeof(Report)); } - - BYTE Report [REPORT_LENGTH]; - } *Queue; - - unsigned ReadIndex, WriteIndex; - } HID; -#endif - CRITICAL_SECTION HIDwriteQueueLock; // queue must be locked before being modified - - // async rumble - HANDLE AsyncRumbleThread; // automatically disables rumble if requested - volatile DWORD AsyncRumbleTimeout; - // orientation estimation - unsigned WiimoteNearGUpdates; - unsigned NunchukNearGUpdates; - // audio - HANDLE SampleThread; - const wiimote_sample* volatile CurrentSample; // otherwise playing square wave - // state recording - struct recording - { - volatile bool bEnabled; - state_history *StateHistory; - volatile DWORD StartTimeMS; - volatile DWORD EndTimeMS; // can be UNTIL_STOP - unsigned TriggerFlags; // wiimote changes trigger a state event - unsigned ExtTriggerFlags;// extension changes " - } Recording; - }; - -#endif // _WIIMOTE_H
\ No newline at end of file |