• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 #include "blt_soft_timer.h"
19 #include "stack/ble/ble.h"
20 #include "tl_common.h"
21 
22 #if BLT_SOFTWARE_TIMER_ENABLE
23 
24 _attribute_ble_data_retention_ blt_soft_timer_t blt_timer;
25 
26 /**
27  * @brief		This function is used to Sort the timers according
28  * 				to the time of the timed task, so as to trigger the
29  * 				timers in turn
30  * @param[in]	none
31  * @return      none
32  */
blt_soft_timer_sort(void)33 int blt_soft_timer_sort(void)
34 {
35     if (blt_timer.currentNum < 1 || blt_timer.currentNum > MAX_TIMER_NUM) {
36         return 0;
37     } else {
38         // BubbleSort
39         int n = blt_timer.currentNum;
40         u8 temp[sizeof(blt_time_event_t)];
41 
42         for (int i = 0; i < n - 1; i++) {
43             for (int j = 0; j < n - i - 1; j++) {
44                 if (TIME_COMPARE_BIG(blt_timer.timer[j].t, blt_timer.timer[j + 1].t)) {
45                     // swap
46                     memcpy(temp, &blt_timer.timer[j], sizeof(blt_time_event_t));
47                     memcpy(&blt_timer.timer[j], &blt_timer.timer[j + 1], sizeof(blt_time_event_t));
48                     memcpy(&blt_timer.timer[j + 1], temp, sizeof(blt_time_event_t));
49                 }
50             }
51         }
52     }
53 
54     return 1;
55 }
56 
57 /**
58  * @brief		This function is used to add new software timer task
59  * @param[in]	func - callback function for software timer task
60  * @param[in]	interval_us - the interval for software timer task
61  * @return      0 - timer task is full, add fail
62  * 				1 - create successfully
63  */
blt_soft_timer_add(blt_timer_callback_t func,u32 interval_us)64 int blt_soft_timer_add(blt_timer_callback_t func, u32 interval_us)
65 {
66     u32 now = clock_time();
67 
68     if (blt_timer.currentNum >= MAX_TIMER_NUM) {  // timer full
69         return 0;
70     } else {
71         blt_timer.timer[blt_timer.currentNum].cb = func;
72         blt_timer.timer[blt_timer.currentNum].interval = interval_us * SYSTEM_TIMER_TICK_1US;
73         blt_timer.timer[blt_timer.currentNum].t = now + blt_timer.timer[blt_timer.currentNum].interval;
74         blt_timer.currentNum++;
75 
76         blt_soft_timer_sort();
77 
78         blc_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
79 
80         return 1;
81     }
82 }
83 
84 /**
85  * @brief		Timer tasks are originally ordered. When deleting, it will
86  * 				be overwritten forward, so the order will not be destroyed
87  * 				and there is no need to reorder
88  * @param[in]	index - the index for some software timer task
89  * @return      0 - delete fail
90  * 				other - delete successfully
91  */
blt_soft_timer_delete_by_index(u8 index)92 int blt_soft_timer_delete_by_index(u8 index)
93 {
94     if (index >= blt_timer.currentNum) {
95         return 0;
96     }
97 
98     for (int i = index; i < blt_timer.currentNum - 1; i++) {
99         memcpy(&blt_timer.timer[i], &blt_timer.timer[i + 1], sizeof(blt_time_event_t));
100     }
101 
102     blt_timer.currentNum--;
103 
104     return 0;
105 }
106 
107 /**
108  * @brief		This function is used to delete timer tasks
109  * @param[in]	func - callback function for software timer task
110  * @return      0 - delete fail
111  * 				1 - delete successfully
112  */
blt_soft_timer_delete(blt_timer_callback_t func)113 int blt_soft_timer_delete(blt_timer_callback_t func)
114 {
115     for (int i = 0; i < blt_timer.currentNum; i++) {
116         if (blt_timer.timer[i].cb == func) {
117             blt_soft_timer_delete_by_index(i);
118 
119             if (i == 0) {  // The most recent timer is deleted, and the time needs to be updated
120                 if ((u32)(blt_timer.timer[0].t - clock_time()) < 3000 * SYSTEM_TIMER_TICK_1MS) {
121                     blc_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
122                 } else {
123                     blc_pm_setAppWakeupLowPower(0, 0);  // disable
124                 }
125             }
126             return 1;
127         }
128     }
129     return 0;
130 }
131 
132 /**
133  * @brief		This function is used to manage software timer tasks
134  * @param[in]	type - the type for trigger
135  * @return      none
136  */
blt_soft_timer_process(int type)137 void blt_soft_timer_process(int type)
138 {
139     if (type == CALLBACK_ENTRY) {  // callback trigger
140     }
141 
142     u32 now = clock_time();
143     if (!blt_timer.currentNum) {
144         blc_pm_setAppWakeupLowPower(0, 0);  // disable
145         return;
146     }
147 
148     if (!blt_is_timer_expired(blt_timer.timer[0].t, now)) {
149         return;
150     }
151 
152     int change_flg = 0;
153     int result;
154     for (int i = 0; i < blt_timer.currentNum; i++) {
155         if (blt_is_timer_expired(blt_timer.timer[i].t, now)) {  // timer trigger
156             if (blt_timer.timer[i].cb == NULL) {
157             } else {
158                 result = blt_timer.timer[i].cb();
159                 if (result < 0) {
160                     blt_soft_timer_delete_by_index(i);
161                 } else if (result == 0) {
162                     change_flg = 1;
163                     blt_timer.timer[i].t = now + blt_timer.timer[i].interval;
164                 } else {  // set new timer interval
165                     change_flg = 1;
166                     blt_timer.timer[i].interval = result * SYSTEM_TIMER_TICK_1US;
167                     blt_timer.timer[i].t = now + blt_timer.timer[i].interval;
168                 }
169             }
170         }
171     }
172 
173     if (blt_timer.currentNum) {  // timer table not empty
174         if (change_flg) {
175             blt_soft_timer_sort();
176         }
177 
178         if ((u32)(blt_timer.timer[0].t - now) < 3000 * SYSTEM_TIMER_TICK_1MS) {
179             blc_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
180         } else {
181             blc_pm_setAppWakeupLowPower(0, 0);  // disable
182         }
183     } else {
184         blc_pm_setAppWakeupLowPower(0, 0);  // disable
185     }
186 }
187 
188 /**
189  * @brief		This function is used to register the call back for pm_appWakeupLowPowerCb
190  * @param[in]	none
191  * @return      none
192  */
blt_soft_timer_init(void)193 void blt_soft_timer_init(void)
194 {
195     blc_pm_registerAppWakeupLowPowerCb(blt_soft_timer_process);
196 }
197 
198 #endif  // end of  BLT_SOFTWARE_TIMER_ENABLE
199