//-------------------------------------------------------------------------- // // This module provides a timer interface for general purpose timing // requirements. // //-------------------------------------------------------------------------- // $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK Mouse/timer.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. // //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // Tick // // Tick requires one 8 bit timer block named "Tick" and configured with the // following parameters: // // Clock: CPU_32_KHz // Capture: Low // Output: None // Period: 32 // CompareValue: 0 // CompareType: Less Than Or Equal // InterruptType: Terminal Count // InterruptAPI: Enable // IntDispatchMode: ActiveStatus // // This will provide a 1ms tick to be used for millisecond resolution // delays. // delays. If the timer calibration feature is enabled, then the period // will be automatically set by the algorithm to meet 1ms timing. // // tickint.asm should have the following code: // // TickINT: // ljmp _Tick // reti //-------------------------------------------------------------------------- //-------------------------------------- // Included files //-------------------------------------- #include "psocgpioint.h" #include "tick.h" #include "appconfig.h" #include PLATFORM_H #include "cypdef.h" #include "timer.h" #include "isr.h" //-------------------------------------- // Local Definitions and Types //-------------------------------------- //-------------------------------------- // Local Function Declarations //-------------------------------------- #pragma interrupt_handler tick_isr void tick_isr(void); static void delay_usec_loop(void); //-------------------------------------- // Local Definitions //-------------------------------------- // System tick, updated every Tick ISR //static TIME_STAMP tick; TIME_STAMP tick; //-------------------------------------------------------------------------- // tick_isr //-------------------------------------------------------------------------- void tick_isr(void) { tick++; } //-------------------------------------------------------------------------- // timer_init //-------------------------------------------------------------------------- void timer_init() { TIMER_CALIBRATE_TIMER(FALSE); timer_timer_on(); } //-------------------------------------------------------------------------- // timer_timer_on //-------------------------------------------------------------------------- void timer_timer_on() { tick = 0; Tick_Start(); Tick_EnableInt(); } //-------------------------------------------------------------------------- // timer_timer_off //-------------------------------------------------------------------------- void timer_timer_off() { Tick_Stop(); Tick_DisableInt(); } //-------------------------------------------------------------------------- // The timer delay routines use cycle counting for delaying a specific // amount of time. These routines are calibrated for a 12MHz clock // frequency. The delay is computed by the following algorithm and is in // clock cycles: // // delay = 20 * ( A + 2 ) // // Most calls to these functions are executed with an lcall instruction // which is 13 clock cycles. If the call is made with the call instruction // it will be 2 cycles shorter, i.e. call = 11 clock cycles. // //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // timer_delay_10_10usec //-------------------------------------------------------------------------- void timer_delay_10_usec(void) { timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); timer_delay_1_usec(); // [13] cycles for lcall asm("mov A, 4"); // [4] cycles asm("jmp _delay_usec_loop"); // [5] cycles } //-------------------------------------------------------------------------- // timer_delay_100_usec50us //-------------------------------------------------------------------------- void timer_delay_50_usec(void) { // [13] cycles for lcall asm("mov A, 28"); // [4] cycles asm("jmp _delay_usec_loop"); // [5] cycles } //-------------------------------------------------------------------------- // timer_delay_100usec //-------------------------------------------------------------------------- void timer_delay_100_usec(void) { timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); // [13] cycles for lcall asm("mov A, 58"); // [4] cycles asm("jmp _delay_usec_loop"); // [5] cycles } //-------------------------------------------------------------------------- // delay_usec_loop //-------------------------------------------------------------------------- static void delay_usec_loop(void) { asm("and A, FFh"); // [4] cycles asm("ljmp fwd"); // [7] cycles asm("fwd:"); // [0] cycles asm("dec A"); // [4] cycles asm("jnz _delay_usec_loop"); // [5] cycles asm("cmp A, 0"); // [5] cycles asm("cmp A, 0"); // [5] cycles // [8] cycles for return } //-------------------------------------------------------------------------- // timer_delay_msec //-------------------------------------------------------------------------- void timer_delay_msec(UINT16 num_milliseconds) { TIME_STAMP cv; cv = tick + MS_TO_TICK(num_milliseconds); while( tick <= cv ) { M8C_Sleep; asm("nop"); asm("nop"); } } //-------------------------------------------------------------------------- // timer_get_time_stamp //-------------------------------------------------------------------------- TIME_STAMP timer_get_time_stamp(void) { return tick; } //-------------------------------------------------------------------------- // timer_delay_incremental //-------------------------------------------------------------------------- void timer_delay_incremental( TIME_STAMP from_timestamp, UINT16 delay_ms ) { UINT16 delta; delta = TICK_TO_MS( MS_TO_TICK(delay_ms) - (tick - from_timestamp) ); if( (INT16)delta > 0 ) { timer_delay_msec( delta ); } } //-------------------------------------------------------------------------- // timer_time_elapsed //-------------------------------------------------------------------------- BOOL timer_time_elapsed(TIME_STAMP from_timestamp, UINT16 elapsed_time_ms) { if( tick > (from_timestamp + MS_TO_TICK(elapsed_time_ms)) ) { return TRUE; } else { return FALSE; } } //-------------------------------------------------------------------------- // timer_delay_50_usec //-------------------------------------------------------------------------- void timer_delay_50_usec() { timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); timer_delay_10_usec(); } //-------------------------------------------------------------------------- // timer_calibrate_timer //-------------------------------------------------------------------------- #ifdef TIMER_CAL void timer_calibrate_timer(BOOL set_timer_on) { UINT8 tick_count; UINT8 i; Tick_Stop(); Tick_DisableInt(); // Set 32KHz Clock parameters if( !set_timer_on ) { // Force Low Power bit, Maximum Bias, Maximum trim // 1) Goto Bank 1 // 2) Set Trim value in ILO_TR (Force low power bit) // 3) Goto Bank 0 asm("or F, 10h"); asm("mov reg[E9h], 97h"); asm("and F, EFh"); } // Set timer to start at maximum period Tick_WritePeriod(255); // This section of code has been cycle counted from Tick_Start // to Tick_bReadTimer to be 12118 cycles, or 1.010ms @ 12MHz. Tick_Start(); // Wait approx. one-millisecond (lots of loop overhead) for(i=0; i<7282; i++) { asm("lcall _timer_delay_10_usec("); } tick_count = Tick_bReadTimer(); Tick_Stop(); // Set timer period to be the number of counts expired Tick_WritePeriod(255 - tick_count); // Restart timer if necessary if( set_timer_on ) { Tick_Start(); Tick_EnableInt(); } } #endif // TIMER_CAL