//-------------------------------------------------------------------------- // // This module provides the main control for the mouse application. It also // implements the two sleep algorithms along with some other housekeeping. // //-------------------------------------------------------------------------- // $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK Mouse/mouse.c $ // $Modtime: 6/16/04 4:38p10/01/04 1:18p $ // $Revision: 910 $ //-------------------------------------------------------------------------- // // 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 "psocgpioint.h" #include "mouse.h" #include "appconfig.h" #include PLATFORM_H #include "timer.h" #include "protocol.h" #include "bind.h" #include "isr.h" #include "buttons.h" #include "testmode.h" #include "battery.h" #include "ls_config.h" #include "debug.h" #include "port.h" #include "mfgtest.h" //-------------------------------------- // Global Variable Definitions //-------------------------------------- BOOL mouse_asleep; BOOL mouse_auto_bind; //-------------------------------------- // Local Defines and Types //-------------------------------------- #ifdef MOUSE_MOTION_NOT_TIME_SLEEP #define MOUSE_SLEEP(n) mouse_sleep(n) #define MOUSE_WAIT_BUTTON_UP() #else #define MOUSE_SLEEP(n) mouse_progressive_sleep(n) #define MOUSE_WAIT_BUTTON_UP() while( !buttons_up() ) #endif #ifdef TWO_WAY #define MOUSE_PROTOCOL_BIND() protocol_bind() #else #define MOUSE_PROTOCOL_BIND() #endif #ifdef DEBUG #define DEBUG_INIT() debug_init() #else #define DEBUG_INIT() #endif #ifdef MOUSE_BATTERY_STATUS #define CACHE_BATTERY_STATUS() mouse_battery_status = battery_status(); #else #define CACHE_BATTERY_STATUS() #endif //-------------------------------------- // Local Function Declarations //-------------------------------------- static void mouse_init(void); static BOOL mouse_sleep(TIME_STAMP*); static void mouse_do_bind(void); static void mouse_optics_cycle(UINT16 off_ms); #ifndef MOUSE_MOTION_NOT_TIME_SLEEP static BOOL mouse_progressive_sleep(TIME_STAMP*); #endif //-------------------------------------- // Local Variable Definitions //-------------------------------------- static TIME_STAMP sleep_timer; static BOOL mouse_asleep; #ifdef MOUSE_BATTERY_STATUS static UINT8 mouse_battery_status; static BOOL mouse_auto_bind; #endif //-------------------------------------------------------------------------- // main //-------------------------------------------------------------------------- void main(void) { TIME_STAMP ts; TX_PACKET pkt; TX_PACKET *radio_pkt; mouse_init(); protocol_init(); MFG_PIN_CHECK(); TEST_EXECUTE(); radio_pkt = (TX_PACKET*)protocol_get_tx_pkt(); while(1) { // Check for auto bind request if( mouse_auto_bind ) { mouse_do_bind(); } // Get poll time stamp ts = timer_get_time_stamp(); // Check for mouse report if( mouse_get_report(&pkt) ) { UINT8 pkt_size; UINT8 resp = NO_DATA; // Send packet do { if( mouse_auto_bind || timer_time_elapsed( ts, MOUSE_TX_TIMEOUT ) ) { break; } radio_pkt->shared.optical.x = pkt.shared.optical.x; radio_pkt->shared.optical.y = pkt.shared.optical.y; // Compute packet size if( pkt.combi != 0 ) { radio_pkt->combi = pkt.combi; pkt_size = 3; } else { pkt_size = 2; } resp = protocol_send_packet(pkt_size); } while( !(resp == DATA_SENT || resp == ACK_DATA) ); #ifdef MOUSE_BATTERY_STATUS // Send battery level if requested via ACK_DATA if( resp == ACK_DATA ) { do { if( mouse_auto_bind || timer_time_elapsed( ts, MOUSE_TX_TIMEOUT ) ) { break; } radio_pkt->shared.battery_level = mouse_battery_status; resp = protocol_send_packet(1); } while( !(resp == DATA_SENT || resp == ACK_DATA) ); } #endif // Update sleep timer sleep_timer = timer_get_time_stamp(); // Delay for remainder of poll period timer_delay_incremental( ts, MOUSE_POLL_IN_MS ); } else if( !MOUSE_SLEEP(&sleep_timer) ) { // Delay for remainder of poll period if not sleeping timer_delay_incremental( ts, MOUSE_POLL_IN_MS ); } } } //-------------------------------------------------------------------------- // mouse_wakeup //-------------------------------------------------------------------------- void mouse_wakeup(void) { mouse_asleep = FALSE; } //-------------------------------------------------------------------------- // mouse_bind //-------------------------------------------------------------------------- void mouse_bind(void) { mouse_auto_bind = TRUE; isr_disable(INT_BIND); } //-------------------------------------------------------------------------- // mouse_power_up //-------------------------------------------------------------------------- void mouse_power_up(void) { MOTION_POWER_UP(); optical_power_up(); buttons_power_up(); wheel_power_up(); bind_button_power_up(); } //-------------------------------------------------------------------------- // mouse_power_down //-------------------------------------------------------------------------- void mouse_power_down() { optical_power_down(); wheel_power_down(); buttons_power_down(); bind_button_power_down(); MOTION_POWER_DOWN(); } //-------------------------------------------------------------------------- // mouse_get_report //-------------------------------------------------------------------------- BOOL mouse_get_report(TX_PACKET *packet) { BOOL report_valid = FALSE; BUTTON_REPORT buttons; WHEEL_REPORT wheel; packet->combi = 0; //------------------------------------------------ Buttons if( buttons_get_report( &buttons ) ) { packet->combi |= buttons.buttons; report_valid = TRUE; } //------------------------------------------------ Optical if( optical_get_report( &packet->shared.optical ) ) { packet->combi = buttons.buttons; report_valid = TRUE; } //-------------------------------------------------- Wheel if( wheel_get_report( &wheel ) ) { packet->combi |= = (wheel.z & 0x1f) | buttons.buttons; report_valid = TRUE; } return report_valid; } //-------------------------------------------------------------------------- // mouse_init //-------------------------------------------------------------------------- static void mouse_init(void) { mouse_asleep = FALSE; #ifdef MOUSE_POWER_ON_BIND SYS_PARAMETERS systmp; mouse_auto_bind = FALSE; NVRAM_READ( &systmp, sizeof(SYS_PARAMETERS) ); if (systmp.networkId.signature != SIGNATURE_BYTE) { mouse_auto_bind = TRUE; } #else mouse_auto_bind = FALSE; #endif mouse_asleep = FALSE; port_init(); isr_init(); timer_init(); timer_delay_msec(600); // Wait for battery level detect to stabalize mouse_battery_status = battery_status(); CACHE_BATTERY_STATUS(); optical_init(); debounce_init(); buttons_init(); wheel_init(); bind_button_init(); MOTION_INIT(); DEBUG_INIT(); sleep_timer = timer_get_time_stamp(); } //-------------------------------------------------------------------------- // mouse_sleep //-------------------------------------------------------------------------- static BOOL mouse_sleep(TIME_STAMP *sleep_ts) { if( timer_time_elapsed(*sleep_ts, MOUSE_OPTIC_OFF_TIME_MS) && buttons_up() ) { mouse_power_down(); mouse_battery_status = battery_status(); CACHE_BATTERY_STATUS(); mouse_asleep = TRUE; timer_timer_off(); while( mouse_asleep ) { // The next instruction after the M8C_Sleep is prefetched. // We insert two NOPs so the compare for the loop isn't // prefetched. This will use the latest value of mouse_asleep // which can be modified by the interrupt that woke us up. M8C_Sleep; asm("nop"); asm("nop"); } timer_timer_on(); mouse_power_up(); TIMER_CALIBRATE_TIMER(TRUE); MOUSE_WAIT_BUTTON_UP(); // Ignore button in time-sleep algorithm *sleep_ts = timer_get_time_stamp(); return TRUE; } return FALSE; } #ifndef MOUSE_MOTION_NOT_TIME_SLEEP //-------------------------------------------------------------------------- // mouse_progressive_sleep //-------------------------------------------------------------------------- #define MOUSE_STEP1 600000 // 10 min #define MOUSE_STEP1_ON 500 // in mS #define MOUSE_STEP2 1800000 // 30 min #define MOUSE_STEP2_ON 1000 // in mS static BOOL mouse_progressive_sleep(TIME_STAMP *sleep_ts) { TIME_STAMP delta = timer_get_time_stamp() - *sleep_ts; if( delta < MS_TO_TICK(MOUSE_OPTIC_OFF_TIME_MS) ) { return FALSE; } else if( delta < MS_TO_TICK(MOUSE_STEP1) ) { mouse_optics_cycle( MOUSE_STEP1_ON ); return TRUE; } else if( delta < MS_TO_TICK(MOUSE_STEP2) ) { mouse_optics_cycle( MOUSE_STEP2_ON ); return TRUE; } else { return mouse_sleep(sleep_ts); } } //-------------------------------------------------------------------------- // mouse_optics_cycle //-------------------------------------------------------------------------- #define MOUSE_OPTICS_RECOVERY_MS 100 static void mouse_optics_cycle(UINT16 off_ms) { optical_power_down(); timer_delay_msec( off_ms ); optical_power_up(); timer_delay_msec( MOUSE_OPTICS_RECOVERY_MS ); } #endif // MOUSE_MOTION_NOT_TIME_SLEEP //-------------------------------------------------------------------------- // mouse_do_bind //-------------------------------------------------------------------------- static void mouse_do_bind(void) { // wait for button up while( (MOUSE_BIND_PORT & MOUSE_BUTTON_BIND) == 0); isr_disable(INT_ZWHEEL); ISR_DISABLE(GPIO_ISR_ZWHEEL_IE_PORT, GPIO_ISR_ZWHEEL_INT); MOUSE_PROTOCOL_BIND(); isr_enable(INT_ZWHEEL); ISR_ENABLE(GPIO_ISR_ZWHEEL_IE_PORT, GPIO_ISR_ZWHEEL_INT); mouse_auto_bind = FALSE; isr_enable(INT_BIND); ISR_ENABLE(GPIO_ISR_BIND_IE_PORT, GPIO_ISR_BIND_INT); }