Difference Analysis Generated by HtmlDiff on 10/26/2004 1:34 PM  

Base file: C:\CY4632_RDK_1_21\Firmware\Source Code\RDK Mouse\optical.c

Modified file: C:\CY4632_RDK_1_3\Firmware\Source Code\RDK Mouse\optical.c

//--------------------------------------------------------------------------
//
// This module implements a serial interface to the Agilent optical chip
// using GPIO lines on the PSoC.  It also provides an interface for reading
// mouse movement.
//
//--------------------------------------------------------------------------
// $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK Mouse/optical.c $
// $Modtime: 6/16/04 4:38p10/11/04 10:58a $
// $Revision: 1012 $
//--------------------------------------------------------------------------
//
// Copyright 2003-2004, Cypress Semiconductor Corporation.
//
// This software is owned by Cypress Semiconductor Corporation (Cypress)
// and is protected by and subject to worldwide patent protection (United
// States and foreign), United States copyright laws and international 
// treaty provisions. Cypress hereby grants to licensee a personal, 
// non-exclusive, non-transferable license to copy, use, modify, create 
// derivative works of, and compile the Cypress Source Code and derivative 
// works for the sole purpose of creating custom software in support of 
// licensee product to be used only in conjunction with a Cypress integrated 
// circuit as specified in the applicable agreement. Any reproduction, 
// modification, translation, compilation, or representation of this 
// software except as specified above is prohibited without the express 
// written permission of Cypress.
//
// Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, 
// WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Cypress reserves the right to make changes without further notice to the
// materials described herein. Cypress does not assume any liability arising
// out of the application or use of any product or circuit described herein.
// Cypress does not authorize its products for use as critical components in
// life-support systems where a malfunction or failure may reasonably be
// expected to result in significant injury to the user. The inclusion of
// Cypress’ product in a life-support systems application implies that the
// manufacturer assumes all risk of such use and in doing so indemnifies
// Cypress against all charges.
//
// Use may be limited by and subject to the applicable Cypress software
// license agreement.
//
//--------------------------------------------------------------------------


//--------------------------------------
// Included files
//--------------------------------------

#include "appconfig.h"
#include "optical.h"
#include "timer.h"
#include PLATFORM_H


//--------------------------------------
// Local Definitions and Types
//--------------------------------------

typedef enum _ADNS_SPI_DIRECTION 
{
    READ  = 0,
    WRITE = 1,

} ADNS_SPI_DIRECTION;


// Agilent Optical sensor

#define REG_PRODUCT_ID                  0x00
#define REG_REVISION_ID                 0x01
#define REG_MOTION                      0x02            
#define REG_DELTA_X                     0x03
#define REG_DELTA_Y                     0x04
#define REG_SQUAL                       0x05
#define REG_AVERAGE_PIXEL               0x06
#define REG_MAXIMUM_PIXEL               0x07
#define REG_CONFIGURATION_BITS          0x0a
#define REG_DATA_OUT_LOWER              0x0c
#define REG_DATA_OUT_UPPER              0x0d
#define REG_SHUTTER_LOWER               0x0e
#define REG_SHUTTER_UPPER               0x0f
#define REG_FRAME_PERIOD_LOWER          0x10
#define REG_FRAME_PERIOD_UPPER          0x11

#define PRODUCT_ID_ID                   0x03
#define REVISION_REV                    0x10

#define MOTION_MOT                      0x80
#define MOTION_FAULT                    0x20
#define MOTION_OVFY                     0x10
#define MOTION_OVFX                     0x08
#define MOTION_RES                      0x01

#define AVERAGE_PIXEL                   0x3f
#define MAXIMUM_PIXEL                   0x3f

#define CONFIGURATION_BITS_RESET        0x80
#define CONFIGURATION_BITS_LED_MODE     0x40
#define CONFIGURATION_BITS_SELF_TEST    0x20
#define CONFIGURATION_BITS_RES          0x10
#define CONFIGURATION_BITS_PIX_DUMP     0x08
#define CONFIGURATION_BITS_SLEEP        0x01


#ifdef MOUSE_800_NOT_400_CPI

#define CONFIG_VALUE    (                             \
                        CONFIGURATION_BITS_LED_MODE | \
                        CONFIGURATION_BITS_RES        \
                        )
                        
#else

#define CONFIG_VALUE   CONFIGURATION_BITS_LED_MODE

#endif

//--------------------------------------
// Local Function Declarations
//--------------------------------------

static UINT8 adns_read(UINT8);
static void  adns_write(UINT8, UINT8);
static UINT8 adns_spi(UINT8 mosiByte, ADNS_SPI_DIRECTION dir);
static void  set_sdio_dir_out(BOOL is_out);


//--------------------------------------
// Local Definitions
//--------------------------------------



//--------------------------------------------------------------------------
// optical_init
//--------------------------------------------------------------------------

void optical_init(void)
{
    UINT8 prod_id;


    MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_PD;
    MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_SDIO;
    MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_SCLK;

    timer_delay_msec(4);

    MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_SCLK;
    MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_SDIO;
    MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_PD;

    timer_delay_msec(1);

    MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_PD;
    
    timer_delay_msec(1);

    adns_write(REG_CONFIGURATION_BITS, CONFIGURATION_BITS_RESET);       

    timer_delay_100_usec();
    timer_delay_100_usec();

    prod_id = adns_read(REG_PRODUCT_ID);

    if( prod_id == PRODUCT_ID_ID )
    {
        adns_write( REG_CONFIGURATION_BITS, CONFIG_VALUE );
    }
    else
    {
        // communication error with optics
        M8C_Stop;
    }
                                         
}


//--------------------------------------------------------------------------
// optical_get_report
//--------------------------------------------------------------------------

BOOL optical_get_report(OPTICAL_REPORT *report)
{
    BOOL  result = FALSE;
    UINT8 motion;
    static UINT8 osc_motion = 0;  // detect +/-1 oscillations in motion


    motion = adns_read(REG_MOTION);
    report->x = 0;
    report->y = 0;
    
    if (motion & MOTION_FAULT)
    {
        optical_init();
    }
    else if( motion & (MOTION_OVFX | MOTION_OVFY) )
    {
        do
        {
            motion = adns_read(REG_MOTION);
            adns_read(REG_DELTA_X);
            adns_read(REG_DELTA_Y);
        }
        while( motion & MOTION_MOT );
    }
    else if (motion & MOTION_MOT)
    {        
        UINT8 x;
        UINT8 y;

        x = report->x =  (INT8)adns_read(REG_DELTA_X);
        y = report->y = -(INT8)adns_read(REG_DELTA_Y);

        // Account for 8-bit sign inversion for case y = -128
        if( y == 0x80 )
        {
            y = report->y = 0x7f;
        }

        // Prevent pointer oscillations when mouse is idle
        if( (x<2 || x==0xFF) && (y<2 || y==0xFF) )
        {
            ++osc_motion;

            if( osc_motion == 0 )
            {
                osc_motion = 0xFF;
            }
        }
        else
        {
            osc_motion = 0;
        }

        // Report valid packet if under oscillation count
        if( osc_motion < 250 )
        {
            result = TRUE;
        }

    }
    
    return result;
}


//--------------------------------------------------------------------------
// optical_power_up
//--------------------------------------------------------------------------

void optical_power_up(void)
{
    MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_PD;
    
    timer_delay_msec(1);
    
    adns_write( REG_CONFIGURATION_BITS, CONFIG_VALUE );
}


//--------------------------------------------------------------------------
// optical_power_down
//--------------------------------------------------------------------------

void optical_power_down(void)
{
    adns_write( REG_CONFIGURATION_BITS, 0 );
    
    MOUSE_OPTICAL_PORT |= (MOUSE_OPTICAL_SCLK | MOUSE_OPTICAL_PD);
}


//--------------------------------------------------------------------------
// adns_read 
//--------------------------------------------------------------------------

static UINT8 adns_read(UINT8 address)
{
    UINT8 data;

    adns_spi((UINT8)(address & 0x7f), WRITE);

    timer_delay_100_usec();

    data = adns_spi(0, READ);

    timer_delay_100_usec();
    timer_delay_10_usec();
    timer_delay_10_usec();

    return data;
}


//--------------------------------------------------------------------------
// adns_write 
//--------------------------------------------------------------------------

static void adns_write(UINT8 address, UINT8 data)
{
    adns_spi((UINT8)(address | 0x80), WRITE);

    adns_spi(data, WRITE);

    timer_delay_100_usec();
}


//--------------------------------------------------------------------------
// adns_spi 
//--------------------------------------------------------------------------

static UINT8 adns_spi(UINT8 mosiByte, ADNS_SPI_DIRECTION dir)
{
    UINT8 misoByte = 0;
    UINT8 i;


    if(dir == READ)
    {
        set_sdio_dir_out(FALSE);
    }
    else
    {
        set_sdio_dir_out(TRUE);
    }

    for(i=0; i<8; i++)
    {
        MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_SCLK;

        if( dir == READ )
        {
            misoByte <<= 1;

            misoByte |= (MOUSE_OPTICAL_PORT & MOUSE_OPTICAL_SDIO) ? 1 : 0;
        }
        else
        {
            if( mosiByte & 0x80 )
            {
                MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_SDIO;
            }
            else
            {
                MOUSE_OPTICAL_PORT &= ~MOUSE_OPTICAL_SDIO;
            }
            
            mosiByte <<= 1;
        }

        MOUSE_OPTICAL_PORT |= MOUSE_OPTICAL_SCLK;

    } 

    return misoByte;
}


//--------------------------------------------------------------------------
// set_sdio_dir_out 
//--------------------------------------------------------------------------

static void set_sdio_dir_out(BOOL is_out)
{
    static BYTE shadow0 = MOUSE_OPTICAL_DM0_INIT;
    static BYTE shadow1 = MOUSE_OPTICAL_DM1_INIT;
    
    if( is_out )
    {
        // strong drive
        shadow0 |= MOUSE_OPTICAL_SDIO;
        shadow1 &= ~MOUSE_OPTICAL_SDIO;
    }
    else
    {
        // high-z
        shadow0 &= ~MOUSE_OPTICAL_SDIO;
        shadow1 |= MOUSE_OPTICAL_SDIO;
    }
    
    MOUSE_OPTICAL_DM0 = shadow0; 
    MOUSE_OPTICAL_DM1 = shadow1;
}