1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright © 2008 Rafaël Carré
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
27 #if INCREASED_SCROLLWHEEL_POLLING
28 #include "button-target.h"
29 /* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */
30 static int poll_scrollwheel
= 0;
32 static inline void do_scrollwheel(void)
34 if (!poll_scrollwheel
)
35 call_tick_tasks(); /* Run through the list of tick tasks
36 * (that includes reading the scrollwheel) */
40 get_scrollwheel(); /* Read the scrollwheel */
43 poll_scrollwheel
^= 1;
46 static inline void do_scrollwheel(void)
48 call_tick_tasks(); /* Run through the list of tick tasks */
52 #if defined(SANSA_C200V2)
53 #include "backlight-target.h"
55 static int timer2_cycles_per_tick
= 0;
56 static int timer2_cycles_pwmon
= 0;
57 static int timer2_cycles_pwmoff
= 0;
58 static int timer2_pwm_state
= 0;
59 static int timer2_pwm_on
= 0;
61 void _set_timer2_pwm_ratio(int ratio
)
63 int cycles
= timer2_cycles_per_tick
;
66 * Rather arbitrary limits, but since the CPU
67 * needs some to time in the interrupt handler
68 * there sure is some limit.
69 * More specifically, if the cycles needed to do
70 * the pwm handling are more than the reloaded counter needs
71 * to reach 0 again it will reload to the old value most
72 * likely leading to a (slight) slowdown in tick rate.
77 * Permanent off, reduce interrupt rate to save power
79 TIMER2_BGLOAD
= cycles
;
87 * Permanent on, reduce interrupt rate to save power
89 TIMER2_BGLOAD
= cycles
;
95 timer2_cycles_pwmon
= cycles
*ratio
/1000;
96 timer2_cycles_pwmoff
= cycles
*(1000-ratio
)/1000;
98 if (timer2_pwm_on
== 0) {
101 TIMER2_BGLOAD
= timer2_cycles_pwmoff
;
105 static void set_timer2_cycles_per_tick(int cycles
)
107 timer2_cycles_per_tick
= cycles
;
110 static inline void do_sw_pwm(void)
112 if (!timer2_pwm_on
) {
113 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
117 timer2_pwm_state
^= 1;
118 if (timer2_pwm_state
) {
119 TIMER2_BGLOAD
= timer2_cycles_pwmoff
;
122 * Always do scrollwheel and tick tasks during the longer cycle for safety,
123 * since the short cycle can be quite short.
124 * (minimum: 1us if ratio is 10 or 990 or 0.5us with scrollwheel,
125 * or just about 6000 clock cycles at 60MHz)
127 if (timer2_cycles_pwmon
> timer2_cycles_pwmoff
)
128 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
130 TIMER2_BGLOAD
= timer2_cycles_pwmon
;
132 if (!(timer2_cycles_pwmon
> timer2_cycles_pwmoff
))
133 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
137 static inline void do_sw_pwm(void)
139 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
142 static void set_timer2_cycles_per_tick(int cycles
)
149 void INT_TIMER2(void)
152 * Timer is stacked as follows:
153 * Lowest layer: Software PWM (if configured)
154 * Alternates timer2 reload value to implement
155 * software pwm at 100Hz (no scrollwheel)
156 * or 200Hz (scrollwheel) with variable pulse width 1% to 99%
157 * Middle layer: Scrollwheel handling (if configured, 200Hz)
158 * Alternate between polling scrollwheel and running tick
159 * tasks (includes scrollwheel polling).
160 * Top layer: Run tick tasks at 100Hz
164 TIMER2_INTCLR
= 0; /* clear interrupt */
167 void tick_start(unsigned int interval_in_ms
)
169 int cycles
= KERNEL_TIMER_FREQ
/ 1000 * interval_in_ms
;
171 CGU_PERI
|= CGU_TIMER2_CLOCK_ENABLE
; /* enable peripheral */
172 VIC_INT_ENABLE
= INTERRUPT_TIMER2
; /* enable interrupt */
174 set_timer2_cycles_per_tick(cycles
);
175 TIMER2_LOAD
= TIMER2_BGLOAD
= cycles
; /* timer period */
177 /* /!\ bit 4 (reserved) must not be modified
178 * periodic mode, interrupt enabled, no prescale, 32 bits counter */
179 TIMER2_CONTROL
= (TIMER2_CONTROL
& (1<<4)) |