5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
24 #if TIMERS > MAX_TIMERS
25 #error "Timers cannot exceed " .. MAX_TIMERS
28 TimerState timersStates
[TIMERS
] = { { 0 } };
30 void timerReset(uint8_t idx
)
32 TimerState
& timerState
= timersStates
[idx
];
33 timerState
.state
= TMR_OFF
; // is changed to RUNNING dep from mode
34 timerState
.val
= g_model
.timers
[idx
].start
;
35 timerState
.val_10ms
= 0 ;
39 void timerSet(int idx
, int val
)
41 TimerState
& timerState
= timersStates
[idx
];
42 timerState
.state
= TMR_OFF
; // is changed to RUNNING dep from mode
44 timerState
.val_10ms
= 0 ;
46 #endif // #if defined(CPUARM)
48 #if defined(CPUARM) || defined(CPUM2560)
51 for (uint8_t i
=0; i
<TIMERS
; i
++) {
52 if (g_model
.timers
[i
].persistent
) {
53 timersStates
[i
].val
= g_model
.timers
[i
].value
;
60 for (uint8_t i
=0; i
<TIMERS
; i
++) {
61 if (g_model
.timers
[i
].persistent
) {
62 TimerState
*timerState
= &timersStates
[i
];
63 if (g_model
.timers
[i
].value
!= (uint16_t)timerState
->val
) {
64 g_model
.timers
[i
].value
= timerState
->val
;
65 storageDirty(EE_MODEL
);
70 #endif // #if defined(CPUARM) || defined(CPUM2560)
72 #if defined(ACCURAT_THROTTLE_TIMER)
73 #define THR_TRG_TRESHOLD 13 // approximately 10% full throttle
75 #define THR_TRG_TRESHOLD 3 // approximately 10% full throttle
78 void evalTimers(int16_t throttle
, uint8_t tick10ms
)
80 for (uint8_t i
=0; i
<TIMERS
; i
++) {
81 tmrmode_t timerMode
= g_model
.timers
[i
].mode
;
82 tmrstart_t timerStart
= g_model
.timers
[i
].start
;
83 TimerState
* timerState
= &timersStates
[i
];
86 if ((timerState
->state
== TMR_OFF
) && (timerMode
!= TMRMODE_THR_TRG
)) {
87 timerState
->state
= TMR_RUNNING
;
92 if (timerMode
== TMRMODE_THR_REL
) {
94 timerState
->sum
+= throttle
;
97 if ((timerState
->val_10ms
+= tick10ms
) >= 100) {
98 if (timerState
->val
== TIMER_MAX
) break;
99 if (timerState
->val
== TIMER_MIN
) break;
101 timerState
->val_10ms
-= 100 ;
102 tmrval_t newTimerVal
= timerState
->val
;
103 if (timerStart
) newTimerVal
= timerStart
- newTimerVal
;
105 if (timerMode
== TMRMODE_ABS
) {
108 else if (timerMode
== TMRMODE_THR
) {
109 if (throttle
) newTimerVal
++;
111 else if (timerMode
== TMRMODE_THR_REL
) {
112 // @@@ open.20.fsguruh: why so complicated? we have already a s_sum field; use it for the half seconds (not showable) as well
113 // check for s_cnt[i]==0 is not needed because we are shure it is at least 1
114 #if defined(ACCURAT_THROTTLE_TIMER)
115 if ((timerState
->sum
/timerState
->cnt
) >= 128) { // throttle was normalized to 0 to 128 value (throttle/64*2 (because - range is added as well)
116 newTimerVal
++; // add second used of throttle
117 timerState
->sum
-= 128*timerState
->cnt
;
120 if ((timerState
->sum
/timerState
->cnt
) >= 32) { // throttle was normalized to 0 to 32 value (throttle/16*2 (because - range is added as well)
121 newTimerVal
++; // add second used of throttle
122 timerState
->sum
-= 32*timerState
->cnt
;
127 else if (timerMode
== TMRMODE_THR_TRG
) {
128 // we can't rely on (throttle || newTimerVal > 0) as a detection if timer should be running
129 // because having persistent timer brakes this rule
130 if ((throttle
> THR_TRG_TRESHOLD
) && timerState
->state
== TMR_OFF
) {
131 timerState
->state
= TMR_RUNNING
; // start timer running
134 // TRACE("Timer[%d] THr triggered", i);
136 if (timerState
->state
!= TMR_OFF
) newTimerVal
++;
139 if (timerMode
> 0) timerMode
-= (TMRMODE_COUNT
-1);
140 if (getSwitch(timerMode
)) {
145 switch (timerState
->state
) {
147 if (timerStart
&& newTimerVal
>=(tmrval_t
)timerStart
) {
148 AUDIO_TIMER_ELAPSED(i
);
149 timerState
->state
= TMR_NEGATIVE
;
150 // TRACE("Timer[%d] negative", i);
154 if (newTimerVal
>= (tmrval_t
)timerStart
+ MAX_ALERT_TIME
) {
155 timerState
->state
= TMR_STOPPED
;
156 // TRACE("Timer[%d] stopped state at %d", i, newTimerVal);
161 if (timerStart
) newTimerVal
= timerStart
- newTimerVal
; // if counting backwards - display backwards
163 if (newTimerVal
!= timerState
->val
) {
164 timerState
->val
= newTimerVal
;
165 if (timerState
->state
== TMR_RUNNING
) {
166 if (g_model
.timers
[i
].countdownBeep
&& g_model
.timers
[i
].start
) {
167 AUDIO_TIMER_COUNTDOWN(i
, newTimerVal
);
169 if (g_model
.timers
[i
].minuteBeep
&& (newTimerVal
% 60)==0) {
170 AUDIO_TIMER_MINUTE(newTimerVal
);
171 // TRACE("Timer[%d] %d minute announcement", i, newTimerVal/60);