diff options
Diffstat (limited to 'firmware/target/arm/as3525/kernel-as3525.c')
-rw-r--r-- | firmware/target/arm/as3525/kernel-as3525.c | 122 |
1 files changed, 119 insertions, 3 deletions
diff --git a/firmware/target/arm/as3525/kernel-as3525.c b/firmware/target/arm/as3525/kernel-as3525.c index 9250f320b9..4c421e50fc 100644 --- a/firmware/target/arm/as3525/kernel-as3525.c +++ b/firmware/target/arm/as3525/kernel-as3525.c | |||
@@ -36,7 +36,7 @@ | |||
36 | /* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */ | 36 | /* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */ |
37 | static int poll_scrollwheel = 0; | 37 | static int poll_scrollwheel = 0; |
38 | 38 | ||
39 | void INT_TIMER2(void) | 39 | static inline void do_scrollwheel(void) |
40 | { | 40 | { |
41 | if (!poll_scrollwheel) | 41 | if (!poll_scrollwheel) |
42 | call_tick_tasks(); /* Run through the list of tick tasks | 42 | call_tick_tasks(); /* Run through the list of tick tasks |
@@ -48,16 +48,131 @@ void INT_TIMER2(void) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | poll_scrollwheel ^= 1; | 50 | poll_scrollwheel ^= 1; |
51 | } | ||
52 | #else | ||
53 | static inline void do_scrollwheel(void) | ||
54 | { | ||
55 | call_tick_tasks(); /* Run through the list of tick tasks */ | ||
56 | } | ||
57 | #endif | ||
58 | |||
59 | #if defined(SANSA_C200V2) | ||
60 | #include "backlight-target.h" | ||
61 | |||
62 | static int timer2_cycles_per_tick = 0; | ||
63 | static int timer2_cycles_pwmon = 0; | ||
64 | static int timer2_cycles_pwmoff = 0; | ||
65 | static int timer2_pwm_state = 0; | ||
66 | static int timer2_pwm_on = 0; | ||
67 | |||
68 | void _set_timer2_pwm_ratio(int ratio) | ||
69 | { | ||
70 | int cycles = timer2_cycles_per_tick; | ||
71 | |||
72 | /* | ||
73 | * Rather arbitrary limits, but since the CPU | ||
74 | * needs some to time in the interrupt handler | ||
75 | * there sure is some limit. | ||
76 | * More specifically, if the cycles needed to do | ||
77 | * the pwm handling are more than the reloaded counter needs | ||
78 | * to reach 0 again it will reload to the old value most | ||
79 | * likely leading to a (slight) slowdown in tick rate. | ||
80 | */ | ||
81 | |||
82 | if (ratio < 10) { | ||
83 | /* | ||
84 | * Permanent off, reduce interrupt rate to save power | ||
85 | */ | ||
86 | TIMER2_BGLOAD = cycles; | ||
87 | timer2_pwm_on = 0; | ||
88 | _backlight_pwm(0); | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | if (ratio > 990) { | ||
93 | /* | ||
94 | * Permanent on, reduce interrupt rate to save power | ||
95 | */ | ||
96 | TIMER2_BGLOAD = cycles; | ||
97 | timer2_pwm_on = 0; | ||
98 | _backlight_pwm(1); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | timer2_cycles_pwmon = cycles*ratio/1000; | ||
103 | timer2_cycles_pwmoff = cycles*(1000-ratio)/1000; | ||
104 | |||
105 | if (timer2_pwm_on == 0) { | ||
106 | timer2_pwm_state = 0; | ||
107 | timer2_pwm_on = 1; | ||
108 | TIMER2_BGLOAD = timer2_cycles_pwmoff; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static void set_timer2_cycles_per_tick(int cycles) | ||
113 | { | ||
114 | timer2_cycles_per_tick = cycles; | ||
115 | } | ||
116 | |||
117 | static inline void do_sw_pwm(void) | ||
118 | { | ||
119 | if (!timer2_pwm_on) { | ||
120 | do_scrollwheel(); /* Handle scrollwheel and tick tasks */ | ||
121 | TIMER2_INTCLR = 0; /* clear interrupt */ | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | timer2_pwm_state ^= 1; | ||
126 | if (timer2_pwm_state) { | ||
127 | TIMER2_BGLOAD = timer2_cycles_pwmoff; | ||
128 | _backlight_pwm(1); | ||
129 | /* | ||
130 | * Always do scrollwheel and tick tasks during the longer cycle for safety, | ||
131 | * since the short cycle can be quite short. | ||
132 | * (minimum: 1us if ratio is 10 or 990 or 0.5us with scrollwheel, | ||
133 | * or just about 6000 clock cycles at 60MHz) | ||
134 | */ | ||
135 | if (timer2_cycles_pwmon > timer2_cycles_pwmoff) | ||
136 | do_scrollwheel(); /* Handle scrollwheel and tick tasks */ | ||
137 | } else { | ||
138 | TIMER2_BGLOAD = timer2_cycles_pwmon; | ||
139 | _backlight_pwm(0); | ||
140 | if (!(timer2_cycles_pwmon > timer2_cycles_pwmoff)) | ||
141 | do_scrollwheel(); /* Handle scrollwheel and tick tasks */ | ||
142 | } | ||
143 | |||
51 | TIMER2_INTCLR = 0; /* clear interrupt */ | 144 | TIMER2_INTCLR = 0; /* clear interrupt */ |
52 | } | 145 | } |
53 | #else | 146 | #else |
147 | static inline void do_sw_pwm(void) | ||
148 | { | ||
149 | do_scrollwheel(); /* Handle scrollwheel and tick tasks */ | ||
150 | } | ||
151 | |||
152 | static void set_timer2_cycles_per_tick(int cycles) | ||
153 | { | ||
154 | (void)cycles; | ||
155 | } | ||
156 | #endif | ||
157 | |||
158 | |||
54 | void INT_TIMER2(void) | 159 | void INT_TIMER2(void) |
55 | { | 160 | { |
56 | call_tick_tasks(); /* Run through the list of tick tasks */ | 161 | /* |
162 | * Timer is stacked as follows: | ||
163 | * Lowest layer: Software PWM (if configured) | ||
164 | * Alternates timer2 reload value to implement | ||
165 | * software pwm at 100Hz (no scrollwheel) | ||
166 | * or 200Hz (scrollwheel) with variable pulse width 1% to 99% | ||
167 | * Middle layer: Scrollwheel handling (if configured, 200Hz) | ||
168 | * Alternate between polling scrollwheel and running tick | ||
169 | * tasks (includes scrollwheel polling). | ||
170 | * Top layer: Run tick tasks at 100Hz | ||
171 | */ | ||
172 | do_sw_pwm(); | ||
57 | 173 | ||
58 | TIMER2_INTCLR = 0; /* clear interrupt */ | 174 | TIMER2_INTCLR = 0; /* clear interrupt */ |
59 | } | 175 | } |
60 | #endif | ||
61 | 176 | ||
62 | void tick_start(unsigned int interval_in_ms) | 177 | void tick_start(unsigned int interval_in_ms) |
63 | { | 178 | { |
@@ -66,6 +181,7 @@ void tick_start(unsigned int interval_in_ms) | |||
66 | CGU_PERI |= CGU_TIMER2_CLOCK_ENABLE; /* enable peripheral */ | 181 | CGU_PERI |= CGU_TIMER2_CLOCK_ENABLE; /* enable peripheral */ |
67 | VIC_INT_ENABLE = INTERRUPT_TIMER2; /* enable interrupt */ | 182 | VIC_INT_ENABLE = INTERRUPT_TIMER2; /* enable interrupt */ |
68 | 183 | ||
184 | set_timer2_cycles_per_tick(cycles); | ||
69 | TIMER2_LOAD = TIMER2_BGLOAD = cycles; /* timer period */ | 185 | TIMER2_LOAD = TIMER2_BGLOAD = cycles; /* timer period */ |
70 | 186 | ||
71 | /* /!\ bit 4 (reserved) must not be modified | 187 | /* /!\ bit 4 (reserved) must not be modified |