+ All Categories

Download - Xbox 360 Mouse

Transcript
  • 7/31/2019 Xbox 360 Mouse

    1/40

    Source path: svn/ trunk/ WinAVR/ XBox360Controller/ MouseDriver.cr35r189123456789101112131415161718192021

    22232425262728293031323334

    35363738394041424344454647

    48495051525354555657

  • 7/31/2019 Xbox 360 Mouse

    2/40

  • 7/31/2019 Xbox 360 Mouse

    3/40

    118119120121122123124125126127128129130131132133134135136137138139140141

    142143144145146147148149150151152153154

    155156157158159160161162163164165166167

    168169170171172173174175176177

  • 7/31/2019 Xbox 360 Mouse

    4/40

    178179180181182183184185186187188189190191192193194195196197198199200201

    202203204205206207208209210211212213214

    215216217218219220221222223224225226227

    228229230231232233234235236237

  • 7/31/2019 Xbox 360 Mouse

    5/40

    238239240241242243244245246247248249250251252253254255256257258259260261

    262263264265266267268269270271272273274

    275276277278279280281282283284285286287

    288289290291292293294295296297

  • 7/31/2019 Xbox 360 Mouse

    6/40

    298299300301302303304305306307308309310311312313314315316317318319320321

    322323324325326327328329330331332333334

    335336337338339340341342343344345346347

    348349350351352353354355356357

  • 7/31/2019 Xbox 360 Mouse

    7/40

    358359360361362363364365366367368369370371372373374375376377378379380381

    382383384385386387388389390391392393394

    395396397398399400401402403404405406407

    408409410411412413414415416417

  • 7/31/2019 Xbox 360 Mouse

    8/40

    418419420421422423424425426427428429430431432433434435436437438439440441

    442443444445446447448449450451452453454

    455456457458459460461462463464465466467

    468469470471472473474475476477

  • 7/31/2019 Xbox 360 Mouse

    9/40

    478479480481482483484485486487488489490491492493494495496497498499500501

    502503504505506507508509510511512513514

    515516517518519520521522523524525526527

    528529530531532533534535536537

  • 7/31/2019 Xbox 360 Mouse

    10/40

    538539540541542543544545546547548549550551552553554555556557558559560561

    562563564565566567568569570571572573574

    575576577578579580581582583584585586587

    588589590591592593594595596597

  • 7/31/2019 Xbox 360 Mouse

    11/40

    598599600601602603604605606607608609610611612613614615616617618619620621

    622623624625626627628629630631632633634

    635636637638639640641642643644645646647

    648649650651652653654655656657

  • 7/31/2019 Xbox 360 Mouse

    12/40

    658659660661662663664665666667668669670671672673674675676677678679680681

    682683684685686687688689690691692693694

    695696697698699700701702703704705706707

    708709710711712713714715716717

  • 7/31/2019 Xbox 360 Mouse

    13/40

    718719720721722723724725726727728729730731732733734735736737738739740741

    742743744745746747748749750751752753754

    755756757758759760761762763764765766767

    768769770771772773774775776777

  • 7/31/2019 Xbox 360 Mouse

    14/40

    778779780781782783784785786787788789790791792793794795796797798799800801

    802803804805806807808809810811812813814

    815816817818819820821822823824825826827

    828829830831832833834835836837

  • 7/31/2019 Xbox 360 Mouse

    15/40

    838839840841842843844845846847848849850851852853854855856857858859860861

    862863864865866867868869870871872873874

    875876877878879880881882883884885886887

    888889890891892893894895896897

  • 7/31/2019 Xbox 360 Mouse

    16/40

    898899900901902903904905906907908909910911912913914915916917918919920921

    922923924925926927928929930931932933934

    935936937938939940941942943944945946947

    948949950951952953954955956957

  • 7/31/2019 Xbox 360 Mouse

    17/40

  • 7/31/2019 Xbox 360 Mouse

    18/40

    101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041

    1042104310441045104610471048104910501051105210531054

    1055105610571058105910601061106210631064106510661067

    1068106910701071107210731074107510761077

  • 7/31/2019 Xbox 360 Mouse

    19/40

    10781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100/*

    ********************************************************************************* MouseDriver.c** Copyright (c) 2009 Richard Burke* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are met:** * Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.*

    * * Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in* the documentation and/or other materials provided with the* distribution.** * Neither the name of the copyright holders nor the names of* contributors may be used to endorse or promote products derived* from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE* POSSIBILITY OF SUCH DAMAGE.** $Rev: 223 $* $Author: rburke $

  • 7/31/2019 Xbox 360 Mouse

    20/40

  • 7/31/2019 Xbox 360 Mouse

    21/40

  • 7/31/2019 Xbox 360 Mouse

    22/40

    static void EventFilter( uint8_t scancode );static ms_scale_t *FindScale( ms_vector_t *vector, ms_range_t ranges[] );static uint8_t GetScancode( void );static uint8_t HasScancode( void );static ms_scale_t *InverseSlope( ms_vector_t *vx, ms_vector_t *vy, ms_scale_t *slope );static ms_vector_t *LogVector( ms_vector_t *vector, uint8_t eol );static void ResetState( void );static void SendByte( uint8_t data );static void SetMouseConfigDefault( void );static void SetMouseFilterDefault( void );static void SetMouseDriverDefault( void );static void TimerInit( void );static ms_vector_t *VectorX( ms_packet_t *packet, ms_vector_t *vector );static ms_vector_t *VectorY( ms_packet_t *packet, ms_vector_t *vector );static uint8_t VectorW( ms_vector_t *vector, ms_scale_t *n, ms_scale_t *ms );

    /********************************************************************************** MS_Init*********************************************************************************/

    void MS_Init( void ){// Initialize the PS2 shift register, ring buffer, and hardware timeoutSetMouseDriverDefault( );

    ms_dispatch.averagex.index = 0;ms_dispatch.averagey.index = 0;

    // Clear reset state machine and selftest flagSetMouseFilterDefault( );

    // Set initial resolution, frequency, and scaleSetMouseConfigDefault( );

    // Enable pullup on clockcbi( MS_CLOCK_DDR, MS_DATA_BIT );cbi( MS_CLOCK_DDR , MS_CLOCK_BIT );sbi( MS_CLOCK_PORT, MS_CLOCK_BIT );

    // Set mouse interruptsms_clock_falling_edge( );ms_clock_clear_interrupt( );ms_clock_enable_interrupt( );

    }

    /*

    ********************************************************************************* MS_EventTask** This task is run by the LUFA scheduler as part of the round robin algorithm.* It polls the mouse buffer for data and passes it to the EventFilter* for processing. It also monitors the timeout trigger. If the trigger has been* tripped then the mouse hasn't sent an update during the previous sample period.* The analog controls are reset to center values.

  • 7/31/2019 Xbox 360 Mouse

    23/40

    *********************************************************************************/void MS_EventTask( void ){

    while( HasScancode( ) )EventFilter( GetScancode( ) );

    if ( ms_trigger.action == 1 ){

    ms_timer_disable_interrupt( );ms_trigger.action = 0;ms_timer_enable_interrupt( );

    EVA_InvokeEventAction( MS_DeltaX( ACTION_VW_IDLE ) );AddValue( &ms_dispatch.averagex, ACTION_VW_IDLE );

    EVA_InvokeEventAction( MS_DeltaY( ACTION_VW_IDLE ) );AddValue( &ms_dispatch.averagey, ACTION_VW_IDLE );

    }}

    /********************************************************************************

    ** EventFilter** Mouse events are handled by the state machine after hard and soft resets.* During a reset sequence the mouse is brought through a series of commands that* enable the scroll wheel, set the resolution, frequency, and scale, and finally* ends with 0xF4 (Enable Data Reporting). The mouse responds with "acknowledge"* (0xFA) then enables data reporting and resets its movement counters.** In stream mode the mouse sends movement data when it detects movement or a change

    * in state of one or more mouse buttons. The maximum rate at which this data may* be reported is known as the sample rate. This parameter ranges from 10 - 200* samples/sec, with a default value of 100 samples/sec. The host may set this value* using the "Set Sample Rate" (0xF3) command.** Note that reporting is disabled by default. The mouse will not actually issueany* movement data packets until it receives the "Enable Data Reporting" (0xF4) command.* Stream mode is the default operating mode, and is otherwise set using the "Set

    * Stream Mode" (0xEA) command.** The event filter expects the mouse to use the following 4-byte movement data* packet:* --------------------------------------------------------------------* |Bit 7 |Bit 6 |Bit 5 |Bit 4 |Bit 3 |Bit 2 |Bit 1 |Bit 0 |* --------------------------------------------------------------------* Byte 1 |Y overflow |X overflow |Y sign |X sign |1 |Middle |Right |Left |* --------------------------------------------------------------------* Byte 2 | X movement |

  • 7/31/2019 Xbox 360 Mouse

    24/40

    * --------------------------------------------------------------------* Byte 3 | Y movement |* --------------------------------------------------------------------* Byte 4 | Z movement |* --------------------------------------------------------------------*********************************************************************************/static void EventFilter( uint8_t scancode ){

    if( scancode == 0xAA && ms_filter.state == 0x02 )SYS_LogByte( 'T', ms_filter.selftest = 1 );

    if( ms_filter.state < ms_filter.size ){

    uint8_t target = pgm_read_byte( &ms_filter.table[ms_filter.state] );

    if( ( scancode == target ) || ( target == 0xFA && scancode == 0xF4 ) ){

    uint8_t byte = pgm_read_byte( &ms_filter.table[ms_filter.state + 1]);

    if( byte == 0xD1 )SendByte( ms_config.resolution );

    else if( byte == 0xD2 )

    SendByte( ( ms_config.scale == 1 )? 0xE6 : 0xE7 );else if( byte == 0xD3 )SendByte( ms_config.frequency );

    else if ( byte > 0x00 )SendByte( byte );

    ms_filter.state += 2;}else if ( ms_filter.retry++ < 5 ){

    ResetState( );}else{

    KB_ErrorStateLed( );ms_filter.state = 0xFF;ms_filter.retry = 0;

    }}

    // Bit 4 of the command byte should always be set. If it is not then something is wrong.

    // Ignore the sample. Hopefully this will eventually get the filter in synchwith

    // the device.else if ( ms_packet.size == 0 && ( scancode & 0x08 ) == 0 ){

    ms_packet.size = 0;}

    // Gather a four byte mouse vector. Forward the bytes to the event handler where button

    // presses are mapped into actions. The X and Y vectors are translated intowiper values

    // and sent to the MCP42010 digital potentiometers.else{

  • 7/31/2019 Xbox 360 Mouse

    25/40

    ms_filter.retry = 0;ms_packet.bytes[ms_packet.size++] = scancode;if( ms_packet.size == sizeof( ms_packet.bytes ) ){

    EventDispatcher( &ms_packet );ms_packet.size = 0;

    }}

    }

    /********************************************************************************** Vector Scale** The first range is for small mouse vectors. These are scaled with a slope of* 75 degrees (actually 75 / 2 since the mouse range is twice that of the digital* pot and therefore has to be cut in half). When using radians the slope is* calculated as TAN(degrees / 180 * PI) / 2. So half of 75 degrees is a slope* of 1.866.** Rather than use floating point math when calculating mx, integer math is used* instead, with a numerator and denominator. Using a denominator of 256 means

    * the numerator is 1.866 * 256 = ~478. A denominator of 256 allows the division* to be done using the shift-right instruction which is very fast.** The offset in the first row brings the wiper value outside of the GamePad dead* zone. For Halo 3 the dead zone is +/-40. The offset in the subsequent rows* is one greater than the biggest value in the previous range.********************************************************************************/static ms_range_t ms_range[] = {

    { lower: 1, upper: 127, scale: { offset: 40, numerator: 179, denominator:256 } }};

    /********************************************************************************** EventDispatcher*********************************************************************************/static void EventDispatcher( ms_packet_t *packet ){

    ms_vector_t vx, vy;ms_scale_t ms, *nx, *ny;uint8_t wx, wy, zsign, z;

    LogVector( VectorX( packet, &vx ), ' ' ); // Extract X vector from the mouse packet.

    LogVector( VectorY( packet, &vy ), '\n' ); // Extract Y vector from the mouse packet.

    InverseSlope( &vx, &vy, &ms ); // ms = M ( 1 - Slope ) as a fraction.

    ms.denominator >>= 5; // 0

  • 7/31/2019 Xbox 360 Mouse

    26/40

    nx = FindScale( &vx, ms_range ); // Find N in table. N = f(X).wx = VectorW( &vx, nx, &ms ); // Calculate Vx = N X + M (1 - S

    lope)

    AddValue( &ms_dispatch.averagex, wx ); // Add X to moving average.

    EVA_InvokeEventAction( MS_DeltaX( Average( &ms_dispatch.averagex ) ) );

    ny = FindScale( &vy, ms_range ); // Find N in table. N = f(Y).wy = VectorW( &vy, ny, &ms ); // Calculate vy = N Y + M (1 - S

    lope)

    AddValue( &ms_dispatch.averagey, wy ); // Add Y to moving average.

    EVA_InvokeEventAction( MS_DeltaY( Average( &ms_dispatch.averagey ) ) );

    if( ! ( packet->left == ms_dispatch.left ) ){

    ms_dispatch.left = packet->left;EVA_InvokeEventAction( ( ms_dispatch.left )? MS_ButtonPress( MLeft ) : M

    S_ButtonRelease( MLeft ) );}

    if( ! ( packet->right == ms_dispatch.right ) ){ms_dispatch.right = packet->right;EVA_InvokeEventAction( ( ms_dispatch.right )? MS_ButtonPress( MRight ) :

    MS_ButtonRelease( MRight ) );}

    if( ! ( packet->middle == ms_dispatch.middle ) ){

    ms_dispatch.middle = packet->middle;EVA_InvokeEventAction( ( ms_dispatch.middle )? MS_ButtonPress( MMiddle )

    : MS_ButtonRelease( MMiddle ) );}

    zsign = packet->z > 128;z = ( zsign )? ~packet->z + 1 : packet->z;if( ms_dispatch.hysteresis )

    ms_dispatch.hysteresis--;

    if( ! ( ( zsign == 0 && z > 1 ) == ms_dispatch.up ) && ms_dispatch.hysteresis > 0 )

    {ms_dispatch.hysteresis = 12;ms_dispatch.up = zsign == 0 && z > 1 ;EVA_InvokeEventAction( ( ms_dispatch.up )? MS_ButtonPress( MWheelUp ) :

    MS_ButtonRelease( MWheelUp ) );

    }

    if( ! ( ( zsign == 1 && z > 1 ) == ms_dispatch.down ) && ms_dispatch.hysteresis > 0 )

    {ms_dispatch.hysteresis = 12;ms_dispatch.up = zsign == 1 && z > 1;EVA_InvokeEventAction( ( ms_dispatch.down )? MS_ButtonPress( MWheelDown

    ) : MS_ButtonRelease( MWheelDown ) );}

  • 7/31/2019 Xbox 360 Mouse

    27/40

    }

    /********************************************************************************** FindScale** Translates X or Y vector component between 0 to +/-255 counts per milli-meter* into an MCP42010 digital POT wiper value between 0 to 255. The translation* uses the formula y = mx + b; where x is the magnitude of the mouse vector;* m is a conversion factor implemented as a fraction with a 16-bit numerator,* and a 16-bit denominator; and b is an 8-bit offset. The resulting wiper value* is proportional to the mouse vector and larger than the game-pad dead-zone.*********************************************************************************/static ms_scale_t *FindScale( ms_vector_t *vector, ms_range_t ranges[] ){

    static ms_scale_t unity = { offset: 0, numerator: 1, denominator: 1 };

    for( uint8_t i = 0; i < sizeof( ms_range ) / sizeof( ms_range_t ); i++ ){

    if( vector->data >= ms_range[i].lower && vector->data label = 'X' - 64;vector->sign = packet->xsign;vector->overflow = packet->xoverflow;vector->data = packet->x;

    return AbsoluteValue( vector );}

    /*

    ********************************************************************************* VectorY*********************************************************************************/ms_vector_t *VectorY( ms_packet_t *packet, ms_vector_t *vector ){

    vector->label = 'Y' - 64;vector->sign = packet->ysign;

  • 7/31/2019 Xbox 360 Mouse

    28/40

    vector->overflow = packet->yoverflow;vector->data = packet->y;

    return AbsoluteValue( vector );}

    /********************************************************************************** AbsoluteValue*********************************************************************************/static ms_vector_t *AbsoluteValue( ms_vector_t *vector ){

    // Need absolute value. Two's complement negative values.if( vector->sign )

    vector->data = ~vector->data + 1;

    // Overflow? We don't want no stinken overflow!if( vector->overflow )

    vector->data = ACTION_VW_MAXVECTOR;

    return vector;

    }

    /********************************************************************************** InverseSlope*********************************************************************************/static ms_scale_t *InverseSlope( ms_vector_t *vx, ms_vector_t *vy, ms_scale_t *slope ){

    uint16_t max = ( vx->data >= vy->data )? vx->data : vy->data;

    uint16_t min = ( vx->data data )? vx->data : vy->data;

    slope->numerator = 256 - min * 256 / max;slope->denominator = 256;slope->offset = 0;

    return slope;}

    /********************************************************************************** VectorW

    *********************************************************************************/static uint8_t VectorW( ms_vector_t *vector, ms_scale_t *n, ms_scale_t *ms ){

    uint8_t wiper;

    wiper = vector->data * n->numerator / n->denominator + n->offset;wiper += ms->numerator / ms->denominator;wiper = ( wiper > ACTION_VW_MAXVECTOR )? ACTION_VW_MAXVECTOR : wiper;

  • 7/31/2019 Xbox 360 Mouse

    29/40

  • 7/31/2019 Xbox 360 Mouse

    30/40

    * The mouse filter takes the PS2 scan codes from the mouse ring buffer and passes* them through the mouse startup sequence, or through packet assembly and* dispatch.** Setting the filter to default values resets the startup sequence state machine* and clears the self-test flag. The self-test flag is used to determine if a* mouse is present.** If the mouse has not sent a self-test passed event then MS_Send( ) is disabled* as it blocks waiting for bus control to be passed from the mouse. No mouse and* you wait forever.*********************************************************************************/static void SetMouseFilterDefault( void ){

    ms_packet.size = 0;

    ms_filter.retry = 0;ms_filter.state = 2;

    SYS_LogByte( 'T', ms_filter.selftest = 0 );ms_filter.size = sizeof( ms_state_table ) / sizeof( uint8_t );ms_filter.table = ms_state_table;

    }

    /********************************************************************************** SetMouseDriverDefault** Bits are clocked from the mouse into a ring buffer within an ISR. The buffer* and ISR shift register are reset in preparation for recieving bits, assembling

    * then into bytes and then stuffing the result into a ring buffer.** Because the mouse doesn't send a zero vector when movement stops, a timer* fires an interrupt when the PS2 interface times out. The timer sets a trigger* that the mouse task uses to send a zero vector to the dispatcher. The timer* and trigger state is initialized.*********************************************************************************/static void SetMouseDriverDefault( void ){

    ms_driver.bit_n = 1;ms_driver.buffer = 0;

    ms_driver.error = 0;RING_Initialize( &ms_driver.ringbuffer, ms_driver.data, sizeof( ms_driver.da

    ta ) );

    ms_trigger.timeout = 15;ms_trigger.timer = 0;ms_trigger.action = 0;

    // Enable timer interrupt (1 per ms)TimerInit( );

  • 7/31/2019 Xbox 360 Mouse

    31/40

    }

    /********************************************************************************** MS_MouseReset** Sets default resolution, sample frequency, and scale then does a soft reset.*********************************************************************************/void MS_MouseReset( void ){

    SetMouseConfigDefault( );SYS_LogByte( 'T', ms_filter.selftest = 1 );ResetState( );SYS_LogByte( 'T', ms_filter.selftest = 0 );

    }

    /********************************************************************************** ResetState*

    * The mouse responds to the 0xFF (Reset) command with "acknowledge" (0xFA) then* enters reset mode. The MS_EventFilter is called by MS_EventTask whenever* MS_ClockInterrupt puts a byte in the receive buffer. During system startup, or* when a Reset command is sent to the mouse, the MS_EventFilter runs the mouse* through a startup sequence. The sequence, coded as a state machine, enables the* scroll wheel and set the resolution, sample frequency, and scale.*********************************************************************************/static void ResetState( void ){

    SendByte( 0xFF );ms_filter.state = 0;}

    /********************************************************************************** MS_SetResolution** The standard mouse has two counters that keep track of movement: the X movement* counter and the Y movement counter. These are 9-bit 2's complement values and* each has an associated overflow flag. Their contents, along with the state of

    * the three mouse buttons, are sent to the host in the form of a 3-byte movement* data packet. The movement counters represent the mouse's offset relative to its* position when the previous movement data packet was issued, or when the last* non-"Resend" (0xFE) command was successfully sent to the host.** When the mouse reads its inputs it records the current state of its buttons and* increments / decrements the movement counters according to the amount of move

  • 7/31/2019 Xbox 360 Mouse

    32/40

    ment* that has occurred since the last input sample. If either of the counters has* overflowed, the appropriate overflow flag is set. Futher modification of the* counter is disabled until it the counters are reset (due to a packet being sent).** This parameter determines the amount by which the movement counters are* incremented / decremented. The default resolution is 4 counts/mm and the host* may change that value using the "Set Resolution" (0xE8) command.** 0xE8 (Set Resolution) - The mouse responds with "acknowledge" (0xFA) then reads* one byte from the host and again responds with "acknowledge" (0xFA) then resets* its movement counters. The byte read from the host determines the resolutionas* follows:** Byte Read* From Host Resolution* 00 1 count/mm* 01 2 count/mm* 02 4 count/mm* 03 8 count/mm

    *********************************************************************************/void MS_SetResolution( uint8_t resolution ){

    ms_config.resolution = resolution;ResetState( );

    }

    /********************************************************************************** MS_SetFrequency

    ** In stream mode the mouse sends movement data when it detects movement or a* change in state of one or more mouse buttons. The maximum rate at which this* data may be reported is known as the sample rate (i.e., frequency). This* parameter ranges from 10 - 200 samples/sec, with a default value of 100* samples/sec. The host may set this value using the "Set Sample Rate" (0xF3)* command. Note that reporting is disabled by default. The mouse will not* actually issue any movement data packets until it receives the "Enable Data* Reporting" (0xF4) command.** 0xF3 (Set Sample Rate) - The mouse responds with "acknowledge" (0xFA) then* reads one more byte from the host. The mouse saves this byte as the new* sample rate. After receiving the sample rate, the mouse again responds with

    * "acknowledge" (0xFA) and resets its movement counters. Valid sample rates* are 10, 20, 40, 60, 80, 100, and 200 samples/sec.*********************************************************************************/void MS_SetFrequency( uint8_t frequency ){

    ms_config.frequency = frequency;ResetState( );

    }

  • 7/31/2019 Xbox 360 Mouse

    33/40

    /********************************************************************************** MS_SetScaling** Scaling = 1 if scaling is 2:1; 0 if scaling is 1:1 (commands 0xE7 and 0xE6).* 0xE7 (Set Scaling 2:1) - The mouse responds with "acknowledge" (0xFA) then* enables 2:1 scaling.* 0xE6 (Set Scaling 1:1) - The mouse responds with "acknowledge" (0xFA) then* enables 1:1 scaling.** This parameter that does not affect the movement counters, but does affect the* reported value of these counters. By default, the mouse uses 1:1 scaling, which* has no effect on the reported mouse movement. However, the host may select 2:1* scaling by issuing the "Set Scaling 2:1" (0xE7) command. If 2:1 scaling is* enabled, the mouse will apply the following algorithm to the movement counters* before sending their contents to the host:** Movement Reported

    * Counter Movement* 0 0* 1 1* 2 1* 3 3* 4 6* 5 9* N > 5 2 * N*********************************************************************************/void MS_SetScaling( uint8_t scale ){

    ms_config.scale = scale;ResetState( );}

    /********************************************************************************** GetScancode** Fetch a byte from the receive buffer. Returns 0 if the buffer is empty. It's* not a good idea to call this routine when the buffer is empty because there* is no sentinal value. All byte values from 0 - 255 are valid. Poll for data* using HasScancode before calling this function.

    *********************************************************************************/

    static uint8_t GetScancode( void ){

    return SYS_LogByte( 'R', RING_GetElement( &ms_driver.ringbuffer ) );}

    /*

  • 7/31/2019 Xbox 360 Mouse

    34/40

  • 7/31/2019 Xbox 360 Mouse

    35/40

    ms_driver.bit_n = 1;

    // 1. Bring the Clock line low for at least 100 microseconds.cbi( MS_CLOCK_PORT, MS_CLOCK_BIT );sbi( MS_CLOCK_DDR, MS_CLOCK_BIT );_delay_us( 100 );

    // 2. Bring the Data line low.cbi( MS_DATA_PORT, MS_DATA_BIT );sbi( MS_DATA_DDR, MS_DATA_BIT );

    // 3. Release the Clock line.cbi( MS_CLOCK_DDR, MS_CLOCK_BIT );sbi( MS_CLOCK_PORT, MS_CLOCK_BIT );loop_until_bit_is_set( MS_CLOCK_PIN, MS_CLOCK_BIT );

    // 4. Wait for the device to bring the Clock line low.loop_until_bit_is_clear( MS_CLOCK_PIN, MS_CLOCK_BIT );

    // 5. Set/Reset the Data line to send data bitsdo {

    if( data & ms_mask )cbi( MS_DATA_DDR, MS_DATA_BIT ); // Take the data line high.

    else

    sbi( MS_DATA_DDR, MS_DATA_BIT ); // Take the data line low.

    // 6. Wait for the device to bring Clock high.loop_until_bit_is_set( MS_CLOCK_PIN, MS_CLOCK_BIT );

    // 7. Wait for the device to bring Clock low.loop_until_bit_is_clear( MS_CLOCK_PIN, MS_CLOCK_BIT );

    // 8A. Repeat steps 5-7 for the other seven data bits} while( ms_mask

  • 7/31/2019 Xbox 360 Mouse

    36/40

    // detecting idle condition otherwise first bit of// ACK may be lost.ms_clock_clear_interrupt( );ms_clock_enable_interrupt( );ms_timer_enable_interrupt( );

    }

    /********************************************************************************** MS_ClockInterrupt** The transmission of data in the forward direction, ie mouse to Host is* done with a frame of 11 bits. The first bit is a Start Bit (Logic 0) followed* by 8 data bits (LSB First), one Parity Bit (Odd Parity) and a Stop Bit (Logic1).* Each bit should be read on the falling edge of the clock.* bit 1: start bit (low)* bits 2 - 9: data bits (least significant bit first)* bit 10: parity bit (odd parity)* bit 11: stop bit (high)*********************************************************************************/

    ISR( MS_ClockInterrupt ){// Reload the mouse timeout and clear trigger.ms_trigger.timer = ms_trigger.timeout;ms_trigger.action = 0;

    // Start bit must be low.if( ms_driver.bit_n == 1 && bit_is_set( MS_DATA_PIN, MS_DATA_BIT ) )

    goto abort;

    // Read data bits and calculate parity.else if( ms_driver.bit_n >= 2 && ms_driver.bit_n

  • 7/31/2019 Xbox 360 Mouse

    37/40

    SYS_LogByte( 'B', ms_driver.buffer );if( ms_driver.error == 0 )

    SendByte( 0xFE );ms_driver.error = 1;goto abort;

    }else{

    RING_AddElement( &ms_driver.ringbuffer, ms_driver.buffer );}ms_driver.buffer = 0;ms_driver.bit_n = 0;ms_driver.error = 0;

    }ms_driver.bit_n++;

    abort:asm volatile ( "nop":: );

    }

    /********************************************************************************** TimerInit

    ** 16-Bit milli-second timer interrupt. Causes MS_TimerInterrupt to be called* once per milli-second.*********************************************************************************/static void TimerInit( void ){

    // Set TCNT1 Timer for 1 mSOCR1A = 250; // Counter reaches 250 every 1 mS (250,0

    00 / 250 = 1000 Hz).TCCR1A = ( 0

  • 7/31/2019 Xbox 360 Mouse

    38/40

    interrupt enabled.}

    /********************************************************************************** MS_TimerInterrupt** Decrement ms_timer to zero. At the transition from 1 to 0 ms_trigger is set to* 1 (true). The trigger is polled and cleared in the MS_EventTask handler. The* trigger is set when the user stops moving the mouse. The ms_timer is reset* during system initialization and whenever the MS_ClockInterrupt recieves* mouse data.*********************************************************************************/ISR( MS_TimerInterrupt ){

    if( ms_trigger.timer > 0 ){

    ms_trigger.timer--;if( ms_trigger.timer == 0 && ms_trigger.action == 0 ){

    ms_trigger.action = 1;}}

    }

    /****************************************************************************************************** div10*****************************************************************************************************/static uint8_t div10( uint8_t value )

    { static const uint8_t _div10[] PROGMEM = {/* 0 - 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10 - 19 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 29 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* 30 - 39 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* 40 - 49 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,/* 50 - 59 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,/* 60 - 69 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,/* 70 - 79 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,/* 80 - 89 */ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,/* 90 - 99 */ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,/* 100 - 109 */ 10,10,10,10,10,10,10,10,10,10,

    /* 110 - 119 */ 11,11,11,11,11,11,11,11,11,11,/* 120 - 129 */ 12,12,12,12,12,12,12,12,12,12,/* 130 - 139 */ 13,13,13,13,13,13,13,13,13,13,/* 140 - 149 */ 14,14,14,14,14,14,14,14,14,14,/* 150 - 159 */ 15,15,15,15,15,15,15,15,15,15,/* 160 - 169 */ 16,16,16,16,16,16,16,16,16,16,/* 170 - 179 */ 17,17,17,17,17,17,17,17,17,17,/* 180 - 189 */ 18,18,18,18,18,18,18,18,18,18,/* 190 - 199 */ 19,19,19,19,19,19,19,19,19,19,/* 200 - 209 */ 20,20,20,20,20,20,20,20,20,20,

  • 7/31/2019 Xbox 360 Mouse

    39/40

    /* 210 - 219 */ 21,21,21,21,21,21,21,21,21,21,/* 220 - 229 */ 22,22,22,22,22,22,22,22,22,22,/* 230 - 239 */ 23,23,23,23,23,23,23,23,23,23,/* 240 - 249 */ 24,24,24,24,24,24,24,24,24,24,/* 250 - 255 */ 25,25,25,25,25,25

    };

    return( pgm_read_byte( &_div10[value] ) );}

    /****************************************************************************************************** mod10*****************************************************************************************************/static uint8_t mod10( uint8_t value ){

    static const uint8_t _mod10[] PROGMEM = {/* 0 - 9 */ 0,1,2,3,4,5,6,7,8,9,/* 10 - 19 */ 0,1,2,3,4,5,6,7,8,9,/* 20 - 29 */ 0,1,2,3,4,5,6,7,8,9,/* 30 - 39 */ 0,1,2,3,4,5,6,7,8,9,

    /* 40 - 49 */ 0,1,2,3,4,5,6,7,8,9,/* 50 - 59 */ 0,1,2,3,4,5,6,7,8,9,/* 60 - 69 */ 0,1,2,3,4,5,6,7,8,9,/* 70 - 79 */ 0,1,2,3,4,5,6,7,8,9,/* 80 - 89 */ 0,1,2,3,4,5,6,7,8,9,/* 90 - 99 */ 0,1,2,3,4,5,6,7,8,9,/* 100 - 109 */ 0,1,2,3,4,5,6,7,8,9,/* 110 - 119 */ 0,1,2,3,4,5,6,7,8,9,/* 120 - 129 */ 0,1,2,3,4,5,6,7,8,9,/* 130 - 139 */ 0,1,2,3,4,5,6,7,8,9,/* 140 - 149 */ 0,1,2,3,4,5,6,7,8,9,/* 150 - 159 */ 0,1,2,3,4,5,6,7,8,9,/* 160 - 169 */ 0,1,2,3,4,5,6,7,8,9,

    /* 170 - 179 */ 0,1,2,3,4,5,6,7,8,9,/* 180 - 189 */ 0,1,2,3,4,5,6,7,8,9,/* 190 - 199 */ 0,1,2,3,4,5,6,7,8,9,/* 200 - 209 */ 0,1,2,3,4,5,6,7,8,9,/* 210 - 219 */ 0,1,2,3,4,5,6,7,8,9,/* 220 - 229 */ 0,1,2,3,4,5,6,7,8,9,/* 230 - 239 */ 0,1,2,3,4,5,6,7,8,9,/* 240 - 249 */ 0,1,2,3,4,5,6,7,8,9,/* 250 - 255 */ 0,1,2,3,4,5

    };

    return( pgm_read_byte( &_mod10[value] ) );}

    /****************************************************************************************************** LogVector*****************************************************************************************************/static ms_vector_t *LogVector( ms_vector_t *vector, uint8_t eol ){

  • 7/31/2019 Xbox 360 Mouse

    40/40

    if( SYS_IsLoggingEnabled( ) ) {usb_serial_putchar( vector->label + 64 );usb_serial_putchar( ' ' );usb_serial_putchar( ( vector->sign )? '-' : '+' );usb_serial_putchar( div10( div10( vector->data ) ) + '0' );usb_serial_putchar( mod10( div10( vector->data ) ) + '0' );usb_serial_putchar( mod10( vector->data ) + '0' );usb_serial_putchar( eol );

    }

    return vector;}


Top Related