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