Home | History | Annotate | Download | only in LIRC
      1 #include "OISConfig.h"
      2 #ifdef OIS_LIRC_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_LIRCRingBuffer_H
     58 #define OIS_LIRCRingBuffer_H
     59 
     60 #include "OISPrereqs.h"
     61 
     62 namespace OIS
     63 {
     64 	struct LIRCEvent
     65 	{
     66 		//! high bit (0x80000000) will be on if button pushed, else it was released
     67 		unsigned int button;
     68 	};
     69 
     70 	/// <summary>
     71 	/// Ring Buffer (fifo) used to store 16bit pcm data
     72 	/// </summary>
     73 	class LIRCRingBuffer
     74 	{
     75 	private:
     76 		//! Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init
     77 		int bufferSize;
     78 		//! Used for wrapping indices with extra bit to distinguish full/empty.
     79 		int bigMask;
     80 		// Used for fitting indices to buffer.
     81 		int smallMask;
     82 
     83 		// Buffer holding the actual event buffers
     84 		LIRCEvent *buffer;
     85 
     86 		//! Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex.
     87 		volatile int writeIndex;
     88 
     89 		//! Index of next readable byte. Set by RingBuffer_AdvanceReadIndex.
     90 		volatile int readIndex;
     91 
     92 	public:
     93 		LIRCRingBuffer( unsigned int numEntries )
     94 		{
     95 			numEntries = RoundUpToNextPowerOf2( numEntries );
     96 
     97 			//2 bytes per short
     98 			bufferSize = (int)numEntries;
     99 			buffer = new LIRCEvent[numEntries];
    100 
    101 			Flush();
    102 
    103 			bigMask = (int)(numEntries*2)-1;
    104 			smallMask = (int)(numEntries)-1;
    105 		}
    106 
    107 		~LIRCRingBuffer()
    108 		{
    109 			delete buffer;
    110 		}
    111 
    112 		unsigned int RoundUpToNextPowerOf2( unsigned int n )
    113 		{
    114 			int numBits = 0;
    115 			if( ((n-1) & n) == 0)
    116 			return n; //Already Power of two.
    117 
    118 			while( n > 0 )
    119 			{
    120 				n= n>>1;
    121 				numBits++;
    122 			}
    123 			return (unsigned int)(1<<numBits);
    124 		}
    125 
    126 
    127 		int GetReadAvailable( )
    128 		{
    129 			return ( (writeIndex - readIndex) & bigMask );
    130 		}
    131 
    132 
    133 		int GetWriteAvailable( )
    134 		{
    135 			return ( bufferSize - GetReadAvailable());
    136 		}
    137 
    138 
    139 		int Write( LIRCEvent *data, int numEntries )
    140 		{
    141 			int size1 = 0, size2 = 0, numWritten;
    142 			int data1Ptr = 0, data2Ptr = 0;
    143 
    144 			numWritten = GetWriteRegions( numEntries, data1Ptr, size1, data2Ptr, size2 );
    145 
    146 			if( size2 > 0 )
    147 			{
    148 				//copy to two parts
    149 				memcpy( &buffer[data1Ptr], data, sizeof(LIRCEvent) * size1 );
    150 				//Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 );
    151 				memcpy( &buffer[data2Ptr], &data[size1], sizeof(LIRCEvent) * size2 );
    152 				//Array.Copy( data, offsetPtr + size1, buffer, data2Ptr, size2 );
    153 			}
    154 			else
    155 			{	//Copy all continous
    156 				memcpy( &buffer[data1Ptr], data, sizeof(LIRCEvent) * size1 );
    157 				//Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 );
    158 			}
    159 			AdvanceWriteIndex( numWritten );
    160 			return numWritten;
    161 		}
    162 
    163 
    164 		/// <summary>
    165 		/// Reads requested number of entries into sent array.
    166 		/// Returns number written
    167 		/// </summary>
    168 		int Read( LIRCEvent *data, int numEntries )
    169 		{
    170 			int size1 = 0, size2 = 0, numRead, data1Ptr = 0, data2Ptr = 0;
    171 
    172 			numRead = GetReadRegions( numEntries, data1Ptr, size1, data2Ptr, size2 );
    173 
    174 			if( size2 > 0 )
    175 			{
    176 				memcpy( data, &buffer[data1Ptr], sizeof(LIRCEvent) * size1 );
    177 				//Array.Copy( buffer, data1Ptr, data, 0, size1 );
    178 				memcpy( &data[size1], &buffer[data2Ptr], sizeof(LIRCEvent) * size2 );
    179 				//Array.Copy( buffer, data2Ptr, data, size1, size2 );
    180 			}
    181 			else
    182 				memcpy( data, &buffer[data1Ptr], sizeof(LIRCEvent) * size1 );
    183 				//Array.Copy( buffer, data1Ptr, data, 0, size1 );
    184 
    185 			AdvanceReadIndex( numRead );
    186 			return numRead;
    187 		}
    188 
    189 	private:
    190 
    191 		int GetWriteRegions( int numEntries, int &dataPtr1, int &sizePtr1,
    192 							 int &dataPtr2, int &sizePtr2 )
    193 		{
    194 			int   index;
    195 			int   available = GetWriteAvailable();
    196 			if( numEntries > available )
    197 				numEntries = available;
    198 
    199 			//Check to see if write is not contiguous.
    200 			index = writeIndex & smallMask;
    201 			if( (index + numEntries) > bufferSize )
    202 			{
    203 				//Write data in two blocks that wrap the buffer.
    204 				int   firstHalf = bufferSize - index;
    205 				dataPtr1 = index;//&buffer[index];
    206 				sizePtr1 = firstHalf;
    207 				dataPtr2 = 0;//&buffer[0];
    208 				sizePtr2 = numEntries - firstHalf;
    209 			}
    210 			else
    211 			{
    212 				dataPtr1 = index;//&buffer[index];
    213 				sizePtr1 = numEntries;
    214 				dataPtr2 = 0;
    215 				sizePtr2 = 0;
    216 			}
    217 			return numEntries;
    218 		}
    219 
    220 
    221 		int GetReadRegions( int numEntries, int &dataPtr1, int &sizePtr1, int &dataPtr2, int &sizePtr2 )
    222 		{
    223 			int   index;
    224 			int   available = GetReadAvailable( );
    225 			if( numEntries > available )
    226 				numEntries = available;
    227 
    228 			// Check to see if read is not contiguous
    229 			index = readIndex & smallMask;
    230 			if( (index + numEntries) > bufferSize )
    231 			{
    232 				// Write data in two blocks that wrap the buffer
    233 				int firstHalf = bufferSize - index;
    234 				dataPtr1 = index;//&buffer[index];
    235 				sizePtr1 = firstHalf;
    236 				dataPtr2 = 0;//&buffer[0];
    237 				sizePtr2 = numEntries - firstHalf;
    238 			}
    239 			else
    240 			{
    241 				dataPtr1 = index;//&buffer[index];
    242 				sizePtr1 = numEntries;
    243 				dataPtr2 = 0;
    244 				sizePtr2 = 0;
    245 			}
    246 			return numEntries;
    247 		}
    248 
    249 
    250 		int AdvanceWriteIndex( int numEntries )
    251 		{
    252 			 return writeIndex = (writeIndex + numEntries) & bigMask;
    253 		}
    254 
    255 
    256 		int AdvanceReadIndex( int numEntries )
    257 		{
    258 			return readIndex = (readIndex + numEntries) & bigMask;
    259 		}
    260 
    261 
    262 		void Flush( )
    263 		{
    264 			writeIndex = readIndex = 0;
    265 		}
    266 	};
    267 }
    268 #endif //#define OIS_LIRCRingBuffer_H
    269 #endif
    270