1 #include "OISConfig.h" 2 #ifdef OIS_WIN32_WIIMOTE_SUPPORT 3 /* 4 The zlib/libpng License 5 6 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com) 7 8 This software is provided 'as-is', without any express or implied warranty. In no event will 9 the authors be held liable for any damages arising from the use of this software. 10 11 Permission is granted to anyone to use this software for any purpose, including commercial 12 applications, and to alter it and redistribute it freely, subject to the following 13 restrictions: 14 15 1. The origin of this software must not be misrepresented; you must not claim that 16 you wrote the original software. If you use this software in a product, 17 an acknowledgment in the product documentation would be appreciated but is 18 not required. 19 20 2. Altered source versions must be plainly marked as such, and must not be 21 misrepresented as being the original software. 22 23 3. This notice may not be removed or altered from any source distribution. 24 25 # ------------------------# 26 # Original License follows: 27 # ------------------------# 28 29 * PortAudio Portable Real-Time Audio Library 30 * Latest version at: http://www.audiomulch.com/portaudio/ 31 * <platform> Implementation 32 * Copyright (c) 1999-2000 <author(s)> 33 * 34 * Permission is hereby granted, free of charge, to any person obtaining 35 * a copy of this software and associated documentation files 36 * (the "Software"), to deal in the Software without restriction, 37 * including without limitation the rights to use, copy, modify, merge, 38 * publish, distribute, sublicense, and/or sell copies of the Software, 39 * and to permit persons to whom the Software is furnished to do so, 40 * subject to the following conditions: 41 * 42 * The above copyright notice and this permission notice shall be 43 * included in all copies or substantial portions of the Software. 44 * 45 * Any person wishing to distribute modifications to the Software is 46 * requested to send the modifications to the original developer so that 47 * they can be incorporated into the canonical version. 48 * 49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 50 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 51 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 52 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 53 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 54 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 55 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56 */ 57 #ifndef OIS_WiiMoteRingBuffer_H 58 #define OIS_WiiMoteRingBuffer_H 59 60 #include "OISPrereqs.h" 61 62 namespace OIS 63 { 64 struct WiiMoteEvent 65 { 66 //! (7 buttons) If a button was just pressed, the bit will be set 67 unsigned int pushedButtons; 68 69 //! (7 buttons) If a button was just released, the bit will be set 70 unsigned int releasedButtons; 71 72 //! Will be true if POV changed this event 73 bool povChanged; 74 75 //! Will be valid if povChanged = true 76 unsigned int povDirection; 77 78 //! Will be valid if a movement just occurred on main motion sensing 79 bool movement; 80 81 //Values of main orientation vector 82 float x, y, z; 83 84 //! Will be valid if a movement just occurred on main motion sensing 85 bool movementChuck; 86 87 //Values of main orientation vector 88 float nunChuckx, nunChucky, nunChuckz; 89 90 //Used to flag when a Nunchuck axis moved 91 bool nunChuckXAxisMoved, nunChuckYAxisMoved; 92 93 //Values of NunChuck JoyStick 94 int nunChuckXAxis, nunChuckYAxis; 95 96 //! clear initial state clearWiiMoteEvent97 void clear() 98 { 99 pushedButtons = releasedButtons = 0; 100 povChanged = false; 101 povDirection = 0; 102 103 movement = false; 104 x = y = z = 0.0f; 105 106 nunChuckx = nunChucky = nunChuckz = 0; 107 movementChuck = false; 108 109 nunChuckXAxisMoved = nunChuckYAxisMoved = false; 110 nunChuckXAxis = nunChuckYAxis = 0; 111 } 112 }; 113 114 /// <summary> 115 /// Ring Buffer (fifo) used to store 16bit pcm data 116 /// </summary> 117 class WiiMoteRingBuffer 118 { 119 private: 120 //! Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init 121 int bufferSize; 122 //! Used for wrapping indices with extra bit to distinguish full/empty. 123 int bigMask; 124 // Used for fitting indices to buffer. 125 int smallMask; 126 127 // Buffer holding the actual event buffers 128 WiiMoteEvent *buffer; 129 130 //! Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. 131 volatile int writeIndex; 132 133 //! Index of next readable byte. Set by RingBuffer_AdvanceReadIndex. 134 volatile int readIndex; 135 136 public: WiiMoteRingBuffer(unsigned int numEntries)137 WiiMoteRingBuffer( unsigned int numEntries ) 138 { 139 numEntries = RoundUpToNextPowerOf2( numEntries ); 140 141 //2 bytes per short 142 bufferSize = (int)numEntries; 143 buffer = new WiiMoteEvent[numEntries]; 144 145 Flush(); 146 147 bigMask = (int)(numEntries*2)-1; 148 smallMask = (int)(numEntries)-1; 149 } 150 ~WiiMoteRingBuffer()151 ~WiiMoteRingBuffer() 152 { 153 delete buffer; 154 } 155 RoundUpToNextPowerOf2(unsigned int n)156 unsigned int RoundUpToNextPowerOf2( unsigned int n ) 157 { 158 int numBits = 0; 159 if( ((n-1) & n) == 0) 160 return n; //Already Power of two. 161 162 while( n > 0 ) 163 { 164 n= n>>1; 165 numBits++; 166 } 167 return (unsigned int)(1<<numBits); 168 } 169 170 GetReadAvailable()171 int GetReadAvailable( ) 172 { 173 return ( (writeIndex - readIndex) & bigMask ); 174 } 175 176 GetWriteAvailable()177 int GetWriteAvailable( ) 178 { 179 return ( bufferSize - GetReadAvailable()); 180 } 181 182 Write(WiiMoteEvent * data,int numEntries)183 int Write( WiiMoteEvent *data, int numEntries ) 184 { 185 int size1 = 0, size2 = 0, numWritten; 186 int data1Ptr = 0, data2Ptr = 0; 187 188 numWritten = GetWriteRegions( numEntries, data1Ptr, size1, data2Ptr, size2 ); 189 190 if( size2 > 0 ) 191 { 192 //copy to two parts 193 memcpy( &buffer[data1Ptr], data, sizeof(WiiMoteEvent) * size1 ); 194 //Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 ); 195 memcpy( &buffer[data2Ptr], &data[size1], sizeof(WiiMoteEvent) * size2 ); 196 //Array.Copy( data, offsetPtr + size1, buffer, data2Ptr, size2 ); 197 } 198 else 199 { //Copy all continous 200 memcpy( &buffer[data1Ptr], data, sizeof(WiiMoteEvent) * size1 ); 201 //Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 ); 202 } 203 AdvanceWriteIndex( numWritten ); 204 return numWritten; 205 } 206 207 208 /// <summary> 209 /// Reads requested number of entries into sent array. 210 /// Returns number written 211 /// </summary> Read(WiiMoteEvent * data,int numEntries)212 int Read( WiiMoteEvent *data, int numEntries ) 213 { 214 int size1 = 0, size2 = 0, numRead, data1Ptr = 0, data2Ptr = 0; 215 216 numRead = GetReadRegions( numEntries, data1Ptr, size1, data2Ptr, size2 ); 217 218 if( size2 > 0 ) 219 { 220 memcpy( data, &buffer[data1Ptr], sizeof(WiiMoteEvent) * size1 ); 221 //Array.Copy( buffer, data1Ptr, data, 0, size1 ); 222 memcpy( &data[size1], &buffer[data2Ptr], sizeof(WiiMoteEvent) * size2 ); 223 //Array.Copy( buffer, data2Ptr, data, size1, size2 ); 224 } 225 else 226 memcpy( data, &buffer[data1Ptr], sizeof(WiiMoteEvent) * size1 ); 227 //Array.Copy( buffer, data1Ptr, data, 0, size1 ); 228 229 AdvanceReadIndex( numRead ); 230 return numRead; 231 } 232 233 private: 234 GetWriteRegions(int numEntries,int & dataPtr1,int & sizePtr1,int & dataPtr2,int & sizePtr2)235 int GetWriteRegions( int numEntries, int &dataPtr1, int &sizePtr1, 236 int &dataPtr2, int &sizePtr2 ) 237 { 238 int index; 239 int available = GetWriteAvailable(); 240 if( numEntries > available ) 241 numEntries = available; 242 243 //Check to see if write is not contiguous. 244 index = writeIndex & smallMask; 245 if( (index + numEntries) > bufferSize ) 246 { 247 //Write data in two blocks that wrap the buffer. 248 int firstHalf = bufferSize - index; 249 dataPtr1 = index;//&buffer[index]; 250 sizePtr1 = firstHalf; 251 dataPtr2 = 0;//&buffer[0]; 252 sizePtr2 = numEntries - firstHalf; 253 } 254 else 255 { 256 dataPtr1 = index;//&buffer[index]; 257 sizePtr1 = numEntries; 258 dataPtr2 = 0; 259 sizePtr2 = 0; 260 } 261 return numEntries; 262 } 263 264 GetReadRegions(int numEntries,int & dataPtr1,int & sizePtr1,int & dataPtr2,int & sizePtr2)265 int GetReadRegions( int numEntries, int &dataPtr1, int &sizePtr1, int &dataPtr2, int &sizePtr2 ) 266 { 267 int index; 268 int available = GetReadAvailable( ); 269 if( numEntries > available ) 270 numEntries = available; 271 272 // Check to see if read is not contiguous 273 index = readIndex & smallMask; 274 if( (index + numEntries) > bufferSize ) 275 { 276 // Write data in two blocks that wrap the buffer 277 int firstHalf = bufferSize - index; 278 dataPtr1 = index;//&buffer[index]; 279 sizePtr1 = firstHalf; 280 dataPtr2 = 0;//&buffer[0]; 281 sizePtr2 = numEntries - firstHalf; 282 } 283 else 284 { 285 dataPtr1 = index;//&buffer[index]; 286 sizePtr1 = numEntries; 287 dataPtr2 = 0; 288 sizePtr2 = 0; 289 } 290 return numEntries; 291 } 292 293 AdvanceWriteIndex(int numEntries)294 int AdvanceWriteIndex( int numEntries ) 295 { 296 return writeIndex = (writeIndex + numEntries) & bigMask; 297 } 298 299 AdvanceReadIndex(int numEntries)300 int AdvanceReadIndex( int numEntries ) 301 { 302 return readIndex = (readIndex + numEntries) & bigMask; 303 } 304 305 Flush()306 void Flush( ) 307 { 308 writeIndex = readIndex = 0; 309 } 310 }; 311 } 312 #endif //#define OIS_WiiMoteRingBuffer_H 313 #endif 314